aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaDecl.cpp115
-rw-r--r--lib/Sema/SemaDeclAttr.cpp3
-rw-r--r--lib/Sema/SemaDeclCXX.cpp9
-rw-r--r--lib/Sema/SemaDeclObjC.cpp2
-rw-r--r--lib/Sema/SemaExprCXX.cpp4
-rw-r--r--lib/Sema/SemaObjCProperty.cpp1
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp3
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp15
-rw-r--r--lib/Sema/TreeTransform.h1
10 files changed, 108 insertions, 48 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index e057a924c7..a95d08262e 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -810,7 +810,8 @@ public:
TypeSourceInfo *TSInfo, QualType T,
IdentifierInfo *Name,
SourceLocation NameLoc,
- VarDecl::StorageClass StorageClass);
+ VarDecl::StorageClass StorageClass,
+ VarDecl::StorageClass StorageClassAsWritten);
virtual void ActOnObjCCatchParam(DeclPtrTy D);
virtual void ActOnParamDefaultArgument(DeclPtrTy param,
SourceLocation EqualLoc,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 115b7bf756..9ef0359118 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -717,7 +717,8 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
FunctionDecl *New = FunctionDecl::Create(Context,
Context.getTranslationUnitDecl(),
Loc, II, R, /*TInfo=*/0,
- FunctionDecl::Extern, false,
+ FunctionDecl::Extern,
+ FunctionDecl::None, false,
/*hasPrototype=*/true);
New->setImplicit();
@@ -728,7 +729,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i)
Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0,
FT->getArgType(i), /*TInfo=*/0,
- VarDecl::None, 0));
+ VarDecl::None, VarDecl::None, 0));
New->setParams(Params.data(), Params.size());
}
@@ -1160,7 +1161,8 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
ParmVarDecl *Param = ParmVarDecl::Create(Context, New,
SourceLocation(), 0,
*ParamType, /*TInfo=*/0,
- VarDecl::None, 0);
+ VarDecl::None, VarDecl::None,
+ 0);
Param->setImplicit();
Params.push_back(Param);
}
@@ -1592,6 +1594,44 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
return Invalid;
}
+/// StorageClassSpecToVarDeclStorageClass - Maps a DeclSpec::SCS to
+/// a VarDecl::StorageClass. Any error reporting is up to the caller:
+/// illegal input values are mapped to VarDecl::None.
+static VarDecl::StorageClass
+StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
+ switch (StorageClassSpec) {
+ case DeclSpec::SCS_unspecified: return VarDecl::None;
+ case DeclSpec::SCS_extern: return VarDecl::Extern;
+ case DeclSpec::SCS_static: return VarDecl::Static;
+ case DeclSpec::SCS_auto: return VarDecl::Auto;
+ case DeclSpec::SCS_register: return VarDecl::Register;
+ case DeclSpec::SCS_private_extern: return VarDecl::PrivateExtern;
+ // Illegal SCSs map to None: error reporting is up to the caller.
+ case DeclSpec::SCS_mutable: // Fall through.
+ case DeclSpec::SCS_typedef: return VarDecl::None;
+ }
+ llvm_unreachable("unknown storage class specifier");
+}
+
+/// StorageClassSpecToFunctionDeclStorageClass - Maps a DeclSpec::SCS to
+/// a FunctionDecl::StorageClass. Any error reporting is up to the caller:
+/// illegal input values are mapped to FunctionDecl::None.
+static FunctionDecl::StorageClass
+StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
+ switch (StorageClassSpec) {
+ case DeclSpec::SCS_unspecified: return FunctionDecl::None;
+ case DeclSpec::SCS_extern: return FunctionDecl::Extern;
+ case DeclSpec::SCS_static: return FunctionDecl::Static;
+ case DeclSpec::SCS_private_extern: return FunctionDecl::PrivateExtern;
+ // Illegal SCSs map to None: error reporting is up to the caller.
+ case DeclSpec::SCS_auto: // Fall through.
+ case DeclSpec::SCS_mutable: // Fall through.
+ case DeclSpec::SCS_register: // Fall through.
+ case DeclSpec::SCS_typedef: return FunctionDecl::None;
+ }
+ llvm_unreachable("unknown storage class specifier");
+}
+
/// ActOnAnonymousStructOrUnion - Handle the declaration of an
/// anonymous structure or union. Anonymous unions are a C++ feature
/// (C++ [class.union]) and a GNU C extension; anonymous structures
@@ -1712,29 +1752,25 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
if (getLangOptions().CPlusPlus)
FieldCollector->Add(cast<FieldDecl>(Anon));
} else {
- VarDecl::StorageClass SC;
- switch (DS.getStorageClassSpec()) {
- default: assert(0 && "Unknown storage class!");
- case DeclSpec::SCS_unspecified: SC = VarDecl::None; break;
- case DeclSpec::SCS_extern: SC = VarDecl::Extern; break;
- case DeclSpec::SCS_static: SC = VarDecl::Static; break;
- case DeclSpec::SCS_auto: SC = VarDecl::Auto; break;
- case DeclSpec::SCS_register: SC = VarDecl::Register; break;
- case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;
- case DeclSpec::SCS_mutable:
+ DeclSpec::SCS SCSpec = DS.getStorageClassSpec();
+ assert(SCSpec != DeclSpec::SCS_typedef &&
+ "Parser allowed 'typedef' as storage class VarDecl.");
+ VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
+ if (SCSpec == DeclSpec::SCS_mutable) {
// mutable can only appear on non-static class members, so it's always
// an error here
Diag(Record->getLocation(), diag::err_mutable_nonmember);
Invalid = true;
SC = VarDecl::None;
- break;
}
+ SCSpec = DS.getStorageClassSpecAsWritten();
+ VarDecl::StorageClass SCAsWritten
+ = StorageClassSpecToVarDeclStorageClass(SCSpec);
Anon = VarDecl::Create(Context, Owner, Record->getLocation(),
/*IdentifierInfo=*/0,
Context.getTypeDeclType(Record),
- TInfo,
- SC);
+ TInfo, SC, SCAsWritten);
}
Anon->setImplicit();
@@ -2332,24 +2368,20 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (getLangOptions().CPlusPlus)
CheckExtraCXXDefaultArguments(D);
- VarDecl *NewVD;
- VarDecl::StorageClass SC;
- switch (D.getDeclSpec().getStorageClassSpec()) {
- default: assert(0 && "Unknown storage class!");
- case DeclSpec::SCS_unspecified: SC = VarDecl::None; break;
- case DeclSpec::SCS_extern: SC = VarDecl::Extern; break;
- case DeclSpec::SCS_static: SC = VarDecl::Static; break;
- case DeclSpec::SCS_auto: SC = VarDecl::Auto; break;
- case DeclSpec::SCS_register: SC = VarDecl::Register; break;
- case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;
- case DeclSpec::SCS_mutable:
+ DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
+ assert(SCSpec != DeclSpec::SCS_typedef &&
+ "Parser allowed 'typedef' as storage class VarDecl.");
+ VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
+ if (SCSpec == DeclSpec::SCS_mutable) {
// mutable can only appear on non-static class members, so it's always
// an error here
Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
D.setInvalidType();
SC = VarDecl::None;
- break;
}
+ SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
+ VarDecl::StorageClass SCAsWritten
+ = StorageClassSpecToVarDeclStorageClass(SCSpec);
IdentifierInfo *II = Name.getAsIdentifierInfo();
if (!II) {
@@ -2423,8 +2455,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
}
- NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
- II, R, TInfo, SC);
+ VarDecl *NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
+ II, R, TInfo, SC, SCAsWritten);
if (D.isInvalidType())
NewVD->setInvalidDecl();
@@ -2802,6 +2834,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
bool isExplicit = D.getDeclSpec().isExplicitSpecified();
+ DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
+ FunctionDecl::StorageClass SCAsWritten
+ = StorageClassSpecToFunctionDeclStorageClass(SCSpec);
+
// Check that the return type is not an abstract class type.
// For record types, this is done by the AbstractClassUsageDiagnoser once
// the class has been completely parsed.
@@ -2862,7 +2898,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Create a FunctionDecl to satisfy the function definition parsing
// code path.
NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(),
- Name, R, TInfo, SC, isInline,
+ Name, R, TInfo, SC, SCAsWritten, isInline,
/*hasPrototype=*/true);
D.setInvalidType();
}
@@ -2911,7 +2947,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// This is a C++ method declaration.
NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
D.getIdentifierLoc(), Name, R, TInfo,
- isStatic, isInline);
+ isStatic, SCAsWritten, isInline);
isVirtualOkay = !isStatic;
} else {
@@ -2928,7 +2964,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
NewFD = FunctionDecl::Create(Context, DC,
D.getIdentifierLoc(),
- Name, R, TInfo, SC, isInline, HasPrototype);
+ Name, R, TInfo, SC, SCAsWritten, isInline,
+ HasPrototype);
}
if (D.isInvalidType())
@@ -3128,6 +3165,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
ParmVarDecl *Param = ParmVarDecl::Create(Context, NewFD,
SourceLocation(), 0,
*AI, /*TInfo=*/0,
+ VarDecl::None,
VarDecl::None, 0);
Param->setImplicit();
Params.push_back(Param);
@@ -4088,8 +4126,10 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
VarDecl::StorageClass StorageClass = VarDecl::None;
+ VarDecl::StorageClass StorageClassAsWritten = VarDecl::None;
if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
StorageClass = VarDecl::Register;
+ StorageClassAsWritten = VarDecl::Register;
} else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) {
Diag(DS.getStorageClassSpecLoc(),
diag::err_invalid_storage_class_in_func_decl);
@@ -4147,7 +4187,8 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// looking like class members in C++.
ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(),
TInfo, parmDeclType, II,
- D.getIdentifierLoc(), StorageClass);
+ D.getIdentifierLoc(),
+ StorageClass, StorageClassAsWritten);
if (D.isInvalidType())
New->setInvalidDecl();
@@ -4176,10 +4217,12 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC,
TypeSourceInfo *TSInfo, QualType T,
IdentifierInfo *Name,
SourceLocation NameLoc,
- VarDecl::StorageClass StorageClass) {
+ VarDecl::StorageClass StorageClass,
+ VarDecl::StorageClass StorageClassAsWritten) {
ParmVarDecl *New = ParmVarDecl::Create(Context, DC, NameLoc, Name,
adjustParameterType(T), TSInfo,
- StorageClass, 0);
+ StorageClass, StorageClassAsWritten,
+ 0);
// Parameters can not be abstract class types.
// For record types, this is done by the AbstractClassUsageDiagnoser once
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 6a1451a4c6..1c07d9b365 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1978,7 +1978,8 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) {
NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
VD->getLocation(), II,
VD->getType(), VD->getTypeSourceInfo(),
- VD->getStorageClass());
+ VD->getStorageClass(),
+ VD->getStorageClassAsWritten());
if (VD->getQualifier()) {
VarDecl *NewVD = cast<VarDecl>(NewD);
NewVD->setQualifierInfo(VD->getQualifier(), VD->getQualifierRange());
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index c6fd53ca61..c8a3a8ab33 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2385,6 +2385,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(Scope *S,
ClassDecl->getLocation(),
/*IdentifierInfo=*/0,
ArgType, /*TInfo=*/0,
+ VarDecl::None,
VarDecl::None, 0);
CopyConstructor->setParams(&FromParam, 1);
if (S)
@@ -2464,7 +2465,9 @@ void Sema::AddImplicitlyDeclaredMembersToClass(Scope *S,
/*FIXME:*/false,
false, 0, 0,
FunctionType::ExtInfo()),
- /*TInfo=*/0, /*isStatic=*/false, /*isInline=*/true);
+ /*TInfo=*/0, /*isStatic=*/false,
+ /*StorageClassAsWritten=*/FunctionDecl::None,
+ /*isInline=*/true);
CopyAssignment->setAccess(AS_public);
CopyAssignment->setImplicit();
CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment());
@@ -2475,6 +2478,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(Scope *S,
ClassDecl->getLocation(),
/*IdentifierInfo=*/0,
ArgType, /*TInfo=*/0,
+ VarDecl::None,
VarDecl::None, 0);
CopyAssignment->setParams(&FromParam, 1);
@@ -4787,7 +4791,8 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType,
Invalid = true;
VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc,
- Name, ExDeclType, TInfo, VarDecl::None);
+ Name, ExDeclType, TInfo, VarDecl::None,
+ VarDecl::None);
if (!Invalid) {
if (const RecordType *RecordTy = ExDeclType->getAs<RecordType>()) {
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index cc1aab4d89..e1973fa5c2 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1565,7 +1565,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
ParmVarDecl* Param
= ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc,
ArgInfo[i].Name, ArgType, DI,
- VarDecl::None, 0);
+ VarDecl::None, VarDecl::None, 0);
if (ArgType->isObjCInterfaceType()) {
Diag(ArgInfo[i].NameLoc,
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index aa9efed6da..9440772fc6 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1208,7 +1208,8 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
FunctionType::ExtInfo());
FunctionDecl *Alloc =
FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), Name,
- FnType, /*TInfo=*/0, FunctionDecl::None, false, true);
+ FnType, /*TInfo=*/0, FunctionDecl::None,
+ FunctionDecl::None, false, true);
Alloc->setImplicit();
if (AddMallocAttr)
@@ -1216,6 +1217,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
0, Argument, /*TInfo=*/0,
+ VarDecl::None,
VarDecl::None, 0);
Alloc->setParams(&Param, 1);
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index c73d815059..d47d6c2994 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -953,6 +953,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
property->getType(),
/*TInfo=*/0,
VarDecl::None,
+ VarDecl::None,
0);
SetterMethod->setMethodParams(Context, &Argument, 1, 1);
CD->addDecl(SetterMethod);
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index a2bd37c0bb..e35d988dc8 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -991,7 +991,8 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
NewDI, NewDI->getType(),
OldParm->getIdentifier(),
OldParm->getLocation(),
- OldParm->getStorageClass());
+ OldParm->getStorageClass(),
+ OldParm->getStorageClassAsWritten());
if (!NewParm)
return 0;
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 18b6829744..10fe176148 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -322,7 +322,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner,
D->getLocation(), D->getIdentifier(),
DI->getType(), DI,
- D->getStorageClass());
+ D->getStorageClass(),
+ D->getStorageClassAsWritten());
Var->setThreadSpecified(D->isThreadSpecified());
Var->setCXXDirectInitializer(D->hasCXXDirectInitializer());
Var->setDeclaredInCondition(D->isDeclaredInCondition());
@@ -991,7 +992,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
FunctionDecl *Function =
FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(),
D->getDeclName(), T, TInfo,
- D->getStorageClass(),
+ D->getStorageClass(), D->getStorageClassAsWritten(),
D->isInlineSpecified(), D->hasWrittenPrototype());
if (Qualifier)
@@ -1210,14 +1211,16 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
Constructor->getLocation(),
Name, T, TInfo,
Constructor->isExplicit(),
- Constructor->isInlineSpecified(), false);
+ Constructor->isInlineSpecified(),
+ false);
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
Name = SemaRef.Context.DeclarationNames.getCXXDestructorName(
SemaRef.Context.getCanonicalType(ClassTy));
Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
Destructor->getLocation(), Name,
- T, Destructor->isInlineSpecified(), false);
+ T, Destructor->isInlineSpecified(),
+ false);
} else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
CanQualType ConvTy
= SemaRef.Context.getCanonicalType(
@@ -1232,7 +1235,9 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
} else {
Method = CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(),
D->getDeclName(), T, TInfo,
- D->isStatic(), D->isInlineSpecified());
+ D->isStatic(),
+ D->getStorageClassAsWritten(),
+ D->isInlineSpecified());
}
if (Qualifier)
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index f9ffd3f41a..e2fdf66442 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -2630,6 +2630,7 @@ TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm) {
NewDI->getType(),
NewDI,
OldParm->getStorageClass(),
+ OldParm->getStorageClassAsWritten(),
/* DefArg */ NULL);
}