aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/DeclSpec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/DeclSpec.cpp')
-rw-r--r--lib/Sema/DeclSpec.cpp95
1 files changed, 74 insertions, 21 deletions
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index b9d2843b0558..a55cdcccee5d 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -173,6 +173,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
unsigned NumExceptions,
Expr *NoexceptExpr,
CachedTokens *ExceptionSpecTokens,
+ ArrayRef<NamedDecl*>
+ DeclsInPrototype,
SourceLocation LocalRangeBegin,
SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,
@@ -204,7 +206,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Fun.ExceptionSpecType = ESpecType;
I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin().getRawEncoding();
I.Fun.ExceptionSpecLocEnd = ESpecRange.getEnd().getRawEncoding();
- I.Fun.NumExceptions = 0;
+ I.Fun.NumExceptionsOrDecls = 0;
I.Fun.Exceptions = nullptr;
I.Fun.NoexceptExpr = nullptr;
I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() ||
@@ -220,16 +222,18 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
// parameter list there (in an effort to avoid new/delete traffic). If it
// is already used (consider a function returning a function pointer) or too
// small (function with too many parameters), go to the heap.
- if (!TheDeclarator.InlineParamsUsed &&
+ if (!TheDeclarator.InlineStorageUsed &&
NumParams <= llvm::array_lengthof(TheDeclarator.InlineParams)) {
I.Fun.Params = TheDeclarator.InlineParams;
+ new (I.Fun.Params) ParamInfo[NumParams];
I.Fun.DeleteParams = false;
- TheDeclarator.InlineParamsUsed = true;
+ TheDeclarator.InlineStorageUsed = true;
} else {
I.Fun.Params = new DeclaratorChunk::ParamInfo[NumParams];
I.Fun.DeleteParams = true;
}
- memcpy(I.Fun.Params, Params, sizeof(Params[0]) * NumParams);
+ for (unsigned i = 0; i < NumParams; i++)
+ I.Fun.Params[i] = std::move(Params[i]);
}
// Check what exception specification information we should actually store.
@@ -238,7 +242,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
case EST_Dynamic:
// new[] an exception array if needed
if (NumExceptions) {
- I.Fun.NumExceptions = NumExceptions;
+ I.Fun.NumExceptionsOrDecls = NumExceptions;
I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions];
for (unsigned i = 0; i != NumExceptions; ++i) {
I.Fun.Exceptions[i].Ty = Exceptions[i];
@@ -255,9 +259,52 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Fun.ExceptionSpecTokens = ExceptionSpecTokens;
break;
}
+
+ if (!DeclsInPrototype.empty()) {
+ assert(ESpecType == EST_None && NumExceptions == 0 &&
+ "cannot have exception specifiers and decls in prototype");
+ I.Fun.NumExceptionsOrDecls = DeclsInPrototype.size();
+ // Copy the array of decls into stable heap storage.
+ I.Fun.DeclsInPrototype = new NamedDecl *[DeclsInPrototype.size()];
+ for (size_t J = 0; J < DeclsInPrototype.size(); ++J)
+ I.Fun.DeclsInPrototype[J] = DeclsInPrototype[J];
+ }
+
return I;
}
+void Declarator::setDecompositionBindings(
+ SourceLocation LSquareLoc,
+ ArrayRef<DecompositionDeclarator::Binding> Bindings,
+ SourceLocation RSquareLoc) {
+ assert(!hasName() && "declarator given multiple names!");
+
+ BindingGroup.LSquareLoc = LSquareLoc;
+ BindingGroup.RSquareLoc = RSquareLoc;
+ BindingGroup.NumBindings = Bindings.size();
+ Range.setEnd(RSquareLoc);
+
+ // We're now past the identifier.
+ SetIdentifier(nullptr, LSquareLoc);
+ Name.EndLocation = RSquareLoc;
+
+ // Allocate storage for bindings and stash them away.
+ if (Bindings.size()) {
+ if (!InlineStorageUsed &&
+ Bindings.size() <= llvm::array_lengthof(InlineBindings)) {
+ BindingGroup.Bindings = InlineBindings;
+ BindingGroup.DeleteBindings = false;
+ InlineStorageUsed = true;
+ } else {
+ BindingGroup.Bindings =
+ new DecompositionDeclarator::Binding[Bindings.size()];
+ BindingGroup.DeleteBindings = true;
+ }
+ std::uninitialized_copy(Bindings.begin(), Bindings.end(),
+ BindingGroup.Bindings);
+ }
+}
+
bool Declarator::isDeclarationOfFunction() const {
for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) {
switch (DeclTypeInfo[i].Kind) {
@@ -511,7 +558,7 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
// OpenCL v1.2 s6.8 changes this to "The auto and register storage-class
// specifiers are not supported."
if (S.getLangOpts().OpenCL &&
- !S.getOpenCLOptions().cl_clang_storage_class_specifiers) {
+ !S.getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers")) {
switch (SC) {
case SCS_extern:
case SCS_private_extern:
@@ -578,14 +625,16 @@ bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
const char *&PrevSpec,
unsigned &DiagID,
const PrintingPolicy &Policy) {
- // Overwrite TSWLoc only if TypeSpecWidth was unspecified, so that
+ // Overwrite TSWRange.Begin only if TypeSpecWidth was unspecified, so that
// for 'long long' we will keep the source location of the first 'long'.
if (TypeSpecWidth == TSW_unspecified)
- TSWLoc = Loc;
+ TSWRange.setBegin(Loc);
// Allow turning long -> long long.
else if (W != TSW_longlong || TypeSpecWidth != TSW_long)
return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
TypeSpecWidth = W;
+ // Remember location of the last 'long'
+ TSWRange.setEnd(Loc);
return false;
}
@@ -965,9 +1014,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
TypeQualifiers)) {
const unsigned NumLocs = 9;
SourceLocation ExtraLocs[NumLocs] = {
- TSWLoc, TSCLoc, TSSLoc, AltiVecLoc,
- TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc, TQ_unalignedLoc
- };
+ TSWRange.getBegin(), TSCLoc, TSSLoc,
+ AltiVecLoc, TQ_constLoc, TQ_restrictLoc,
+ TQ_volatileLoc, TQ_atomicLoc, TQ_unalignedLoc};
FixItHint Hints[NumLocs];
SourceLocation FirstLoc;
for (unsigned I = 0; I != NumLocs; ++I) {
@@ -1009,8 +1058,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
// Only 'short' and 'long long' are valid with vector bool. (PIM 2.1)
if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short) &&
(TypeSpecWidth != TSW_longlong))
- S.Diag(TSWLoc, diag::err_invalid_vector_bool_decl_spec)
- << getSpecifierName((TSW)TypeSpecWidth);
+ S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_bool_decl_spec)
+ << getSpecifierName((TSW)TypeSpecWidth);
// vector bool long long requires VSX support or ZVector.
if ((TypeSpecWidth == TSW_longlong) &&
@@ -1027,7 +1076,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
// vector long double and vector long long double are never allowed.
// vector double is OK for Power7 and later, and ZVector.
if (TypeSpecWidth == TSW_long || TypeSpecWidth == TSW_longlong)
- S.Diag(TSWLoc, diag::err_invalid_vector_long_double_decl_spec);
+ S.Diag(TSWRange.getBegin(),
+ diag::err_invalid_vector_long_double_decl_spec);
else if (!S.Context.getTargetInfo().hasFeature("vsx") &&
!S.getLangOpts().ZVector)
S.Diag(TSTLoc, diag::err_invalid_vector_double_decl_spec);
@@ -1038,10 +1088,11 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
} else if (TypeSpecWidth == TSW_long) {
// vector long is unsupported for ZVector and deprecated for AltiVec.
if (S.getLangOpts().ZVector)
- S.Diag(TSWLoc, diag::err_invalid_vector_long_decl_spec);
+ S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_long_decl_spec);
else
- S.Diag(TSWLoc, diag::warn_vector_long_decl_spec_combination)
- << getSpecifierName((TST)TypeSpecType, Policy);
+ S.Diag(TSWRange.getBegin(),
+ diag::warn_vector_long_decl_spec_combination)
+ << getSpecifierName((TST)TypeSpecType, Policy);
}
if (TypeAltiVecPixel) {
@@ -1074,8 +1125,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // short -> short int, long long -> long long int.
else if (TypeSpecType != TST_int) {
- S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth
- << getSpecifierName((TST)TypeSpecType, Policy);
+ S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
+ << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
TypeSpecOwned = false;
}
@@ -1084,8 +1135,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // long -> long int.
else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
- S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth
- << getSpecifierName((TST)TypeSpecType, Policy);
+ S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
+ << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
TypeSpecOwned = false;
}
@@ -1267,6 +1318,7 @@ bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc,
switch (VS) {
default: llvm_unreachable("Unknown specifier!");
case VS_Override: VS_overrideLoc = Loc; break;
+ case VS_GNU_Final:
case VS_Sealed:
case VS_Final: VS_finalLoc = Loc; break;
}
@@ -1279,6 +1331,7 @@ const char *VirtSpecifiers::getSpecifierName(Specifier VS) {
default: llvm_unreachable("Unknown specifier");
case VS_Override: return "override";
case VS_Final: return "final";
+ case VS_GNU_Final: return "__final";
case VS_Sealed: return "sealed";
}
}