diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2013-04-03 19:22:20 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2013-04-03 19:22:20 +0000 |
commit | 4f8a3eb2ce5d4ba422483439e20c8cbb4d953a41 (patch) | |
tree | da183dd16cf78a8e3e464f1e041cd33f425ab580 /lib/Sema/SemaDecl.cpp | |
parent | f9f30791dd20472675de012105219cd975ad1076 (diff) |
Revert 178663.
Looks like it broke http://lab.llvm.org:8011/builders/clang-x86_64-darwin10-gdb
Revert "Don't compute a patched/semantic storage class."
This reverts commit 8f187f62cb0487d31bc4afdfcd47e11fe9a51d05.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178681 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 124 |
1 files changed, 94 insertions, 30 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a6ba68060d..16887da457 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1557,7 +1557,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Context.getTranslationUnitDecl(), Loc, Loc, II, R, /*TInfo=*/0, SC_Extern, - false, + SC_None, false, /*hasPrototype=*/true); New->setImplicit(); @@ -1570,7 +1570,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, ParmVarDecl::Create(Context, New, SourceLocation(), SourceLocation(), 0, FT->getArgType(i), /*TInfo=*/0, - SC_None, 0); + SC_None, SC_None, 0); parm->setScopeInfo(0, i); Params.push_back(parm); } @@ -2306,12 +2306,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { // Don't complain about this if we're in GNU89 mode and the old function // is an extern inline function. - // Don't complain about specializations. They are not supposed to have - // storage classes. if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) && New->getStorageClass() == SC_Static && Old->getStorageClass() != SC_Static && - !New->getTemplateSpecializationInfo() && !canRedefineFunction(Old, getLangOpts())) { if (getLangOpts().MicrosoftExt) { Diag(New->getLocation(), diag::warn_static_non_static) << New; @@ -2603,7 +2600,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { SourceLocation(), SourceLocation(), 0, *ParamType, /*TInfo=*/0, - SC_None, + SC_None, SC_None, 0); Param->setScopeInfo(0, Params.size()); Param->setImplicit(); @@ -2719,6 +2716,11 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, // Merge the attributes mergeDeclAttributes(New, Old); + // Merge the storage class. + if (Old->getStorageClass() != SC_Extern && + Old->getStorageClass() != SC_None) + New->setStorageClass(Old->getStorageClass()); + // Merge "pure" flag. if (Old->isPure()) New->setPure(); @@ -2896,8 +2898,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous, // identifier has external linkage. if (New->hasExternalStorage() && Old->hasLinkage()) /* Okay */; - else if (New->getCanonicalDecl()->getStorageClass() != SC_Static && - Old->getCanonicalDecl()->getStorageClass() == SC_Static) { + else if (New->getStorageClass() != SC_Static && + Old->getStorageClass() == SC_Static) { Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); @@ -2957,6 +2959,17 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous, return; } + // c99 6.2.2 P4. + // For an identifier declared with the storage-class specifier extern in a + // scope in which a prior declaration of that identifier is visible, if + // the prior declaration specifies internal or external linkage, the linkage + // of the identifier at the later declaration is the same as the linkage + // specified at the prior declaration. + // FIXME. revisit this code. + if (New->hasExternalStorage() && + Old->getLinkage() == InternalLinkage) + New->setStorageClass(Old->getStorageClass()); + // Merge "used" flag. if (Old->isUsed(false)) New->setUsed(); @@ -3328,6 +3341,25 @@ StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec) { llvm_unreachable("unknown storage class specifier"); } +/// StorageClassSpecToFunctionDeclStorageClass - Maps a DeclSpec::SCS to +/// a StorageClass. Any error reporting is up to the caller: +/// illegal input values are mapped to SC_None. +static StorageClass +StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec) { + switch (StorageClassSpec) { + case DeclSpec::SCS_unspecified: return SC_None; + case DeclSpec::SCS_extern: return SC_Extern; + case DeclSpec::SCS_static: return SC_Static; + case DeclSpec::SCS_private_extern: return SC_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 SC_None; + } + llvm_unreachable("unknown storage class specifier"); +} + /// BuildAnonymousStructOrUnion - Handle the declaration of an /// anonymous structure or union. Anonymous unions are a C++ feature /// (C++ [class.union]) and a C11 feature; anonymous structures @@ -3524,12 +3556,15 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Invalid = true; SC = SC_None; } + SCSpec = DS.getStorageClassSpecAsWritten(); + VarDecl::StorageClass SCAsWritten + = StorageClassSpecToVarDeclStorageClass(SCSpec); Anon = VarDecl::Create(Context, Owner, DS.getLocStart(), Record->getLocation(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), - TInfo, SC); + TInfo, SC, SCAsWritten); // Default-initialize the implicit variable. This initialization will be // trivial in almost all cases, except if a union member has an in-class @@ -4644,7 +4679,7 @@ static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) { static bool shouldConsiderLinkage(const VarDecl *VD) { const DeclContext *DC = VD->getDeclContext()->getRedeclContext(); if (DC->isFunctionOrMethod()) - return VD->hasExternalStorage(); + return VD->hasExternalStorageAsWritten(); if (DC->isFileContext()) return true; if (DC->isRecord()) @@ -4691,6 +4726,10 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, SC = SC_None; } + SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten(); + VarDecl::StorageClass SCAsWritten + = StorageClassSpecToVarDeclStorageClass(SCSpec); + IdentifierInfo *II = Name.getAsIdentifierInfo(); if (!II) { Diag(D.getIdentifierLoc(), diag::err_bad_variable_name) @@ -4720,6 +4759,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // OpenCL __local address space. if (R.getAddressSpace() == LangAS::opencl_local) { SC = SC_OpenCLWorkGroupLocal; + SCAsWritten = SC_OpenCLWorkGroupLocal; } // OpenCL v1.2 s6.9.b p4: @@ -4752,7 +4792,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (!getLangOpts().CPlusPlus) { NewVD = VarDecl::Create(Context, DC, D.getLocStart(), D.getIdentifierLoc(), II, - R, TInfo, SC); + R, TInfo, SC, SCAsWritten); if (D.isInvalidType()) NewVD->setInvalidDecl(); @@ -4822,7 +4862,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewVD = VarDecl::Create(Context, DC, D.getLocStart(), D.getIdentifierLoc(), II, - R, TInfo, SC); + R, TInfo, SC, SCAsWritten); // If this decl has an auto type in need of deduction, make a note of the // Decl so we can diagnose uses of it in its own initializer. @@ -4904,6 +4944,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, (NewVD->hasAttr<CUDASharedAttr>() || NewVD->hasAttr<CUDAConstantAttr>())) { NewVD->setStorageClass(SC_Static); + NewVD->setStorageClassAsWritten(SC_Static); } } @@ -5643,6 +5684,9 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, FunctionDecl *NewFD = 0; bool isInline = D.getDeclSpec().isInlineSpecified(); + DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten(); + FunctionDecl::StorageClass SCAsWritten + = StorageClassSpecToFunctionDeclStorageClass(SCSpec); if (!SemaRef.getLangOpts().CPlusPlus) { // Determine whether the function was written with a @@ -5656,8 +5700,8 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getLocStart(), NameInfo, R, - TInfo, SC, isInline, - HasPrototype, false); + TInfo, SC, SCAsWritten, isInline, + HasPrototype); if (D.isInvalidType()) NewFD->setInvalidDecl(); @@ -5724,7 +5768,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, return FunctionDecl::Create(SemaRef.Context, DC, D.getLocStart(), D.getIdentifierLoc(), Name, R, TInfo, - SC, isInline, + SC, SCAsWritten, isInline, /*hasPrototype=*/true, isConstexpr); } @@ -5755,21 +5799,36 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, return 0; } + bool isStatic = SC == SC_Static; + + // [class.free]p1: + // Any allocation function for a class T is a static member + // (even if not explicitly declared static). + if (Name.getCXXOverloadedOperator() == OO_New || + Name.getCXXOverloadedOperator() == OO_Array_New) + isStatic = true; + + // [class.free]p6 Any deallocation function for a class X is a static member + // (even if not explicitly declared static). + if (Name.getCXXOverloadedOperator() == OO_Delete || + Name.getCXXOverloadedOperator() == OO_Array_Delete) + isStatic = true; + + IsVirtualOkay = !isStatic; + // This is a C++ method declaration. - CXXMethodDecl *Ret = CXXMethodDecl::Create(SemaRef.Context, - cast<CXXRecordDecl>(DC), - D.getLocStart(), NameInfo, R, - TInfo, SC, isInline, - isConstexpr, SourceLocation()); - IsVirtualOkay = !Ret->isStatic(); - return Ret; + return CXXMethodDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC), + D.getLocStart(), NameInfo, R, + TInfo, isStatic, SCAsWritten, isInline, + isConstexpr, SourceLocation()); + } else { // Determine whether the function was written with a // prototype. This true when: // - we're in C++ (where every function has a prototype), return FunctionDecl::Create(SemaRef.Context, DC, D.getLocStart(), - NameInfo, R, TInfo, SC, isInline, + NameInfo, R, TInfo, SC, SCAsWritten, isInline, true/*HasPrototype*/, isConstexpr); } } @@ -6335,7 +6394,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // A storage-class-specifier shall not be specified in an explicit // specialization (14.7.3) if (SC != SC_None) { - if (SC != NewFD->getTemplateSpecializationInfo()->getTemplate()->getTemplatedDecl()->getStorageClass()) + if (SC != NewFD->getStorageClass()) Diag(NewFD->getLocation(), diag::err_explicit_specialization_inconsistent_storage_class) << SC @@ -7588,7 +7647,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, VDecl->setInvalidDecl(); } } else if (VDecl->isFileVarDecl()) { - if (VDecl->getStorageClass() == SC_Extern && + if (VDecl->getStorageClassAsWritten() == SC_Extern && (!getLangOpts().CPlusPlus || !(Context.getBaseElementType(VDecl->getType()).isConstQualified() || VDecl->isExternC()))) @@ -7878,7 +7937,7 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) { // for-range-declaration cannot be given a storage class specifier. int Error = -1; - switch (VD->getStorageClass()) { + switch (VD->getStorageClassAsWritten()) { case SC_None: break; case SC_Extern: @@ -8192,11 +8251,14 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. // C++03 [dcl.stc]p2 also permits 'auto'. VarDecl::StorageClass StorageClass = SC_None; + VarDecl::StorageClass StorageClassAsWritten = SC_None; if (DS.getStorageClassSpec() == DeclSpec::SCS_register) { StorageClass = SC_Register; + StorageClassAsWritten = SC_Register; } else if (getLangOpts().CPlusPlus && DS.getStorageClassSpec() == DeclSpec::SCS_auto) { StorageClass = SC_Auto; + StorageClassAsWritten = SC_Auto; } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) { Diag(DS.getStorageClassSpecLoc(), diag::err_invalid_storage_class_in_func_decl); @@ -8269,7 +8331,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { D.getLocStart(), D.getIdentifierLoc(), II, parmDeclType, TInfo, - StorageClass); + StorageClass, StorageClassAsWritten); if (D.isInvalidType()) New->setInvalidDecl(); @@ -8308,7 +8370,7 @@ ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, location for the unnamed parameters, embedding the parameter's type? */ ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, 0, T, Context.getTrivialTypeSourceInfo(T, Loc), - SC_None, 0); + SC_None, SC_None, 0); Param->setImplicit(); return Param; } @@ -8361,7 +8423,8 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param, ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, SourceLocation NameLoc, IdentifierInfo *Name, QualType T, TypeSourceInfo *TSInfo, - VarDecl::StorageClass StorageClass) { + VarDecl::StorageClass StorageClass, + VarDecl::StorageClass StorageClassAsWritten) { // In ARC, infer a lifetime qualifier for appropriate parameter types. if (getLangOpts().ObjCAutoRefCount && T.getObjCLifetime() == Qualifiers::OCL_None && @@ -8388,7 +8451,8 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name, Context.getAdjustedParameterType(T), TSInfo, - StorageClass, 0); + StorageClass, StorageClassAsWritten, + 0); // Parameters can not be abstract class types. // For record types, this is done by the AbstractClassUsageDiagnoser once |