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 | |
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
38 files changed, 339 insertions, 220 deletions
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index d9a3364606..504553c17a 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -111,14 +111,9 @@ succeeded). Essentially all previous 'cast' usage should be replaced with 'castAs' and 'dyn_cast' should be replaced with 'getAs'. See r175462 for the first example of such a change along with many examples of how code was migrated to the new API. - -Storage Class -^^^^^^^^^^^^^ - -For each variable and function Clang used to keep the storage class as written -in the source, the linkage and a semantic storage class. This was a bit -redundant and the semantic storage class has been removed. The method -getStorageClass now returns what is written it the source code for that decl. + +API change 1 +^^^^^^^^^^^^ ... diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 0294b9fde8..c89c73134c 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -660,6 +660,7 @@ private: friend class ASTDeclReader; unsigned SClass : 3; + unsigned SClassAsWritten : 3; unsigned ThreadSpecified : 1; unsigned InitStyle : 2; @@ -726,12 +727,14 @@ protected: VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, StorageClass SC) + QualType T, TypeSourceInfo *TInfo, StorageClass SC, + StorageClass SCAsWritten) : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Init() { assert(sizeof(VarDeclBitfields) <= sizeof(unsigned)); assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned)); AllBits = 0; VarDeclBits.SClass = SC; + VarDeclBits.SClassAsWritten = SCAsWritten; // Everything else is implicitly initialized to false. } @@ -754,18 +757,23 @@ public: static VarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S); + StorageClass S, StorageClass SCAsWritten); static VarDecl *CreateDeserialized(ASTContext &C, unsigned ID); virtual SourceRange getSourceRange() const LLVM_READONLY; - /// \brief Returns the storage class as written in the source. For the - /// computed linkage of symbol, see getLinkage. StorageClass getStorageClass() const { return (StorageClass) VarDeclBits.SClass; } + StorageClass getStorageClassAsWritten() const { + return (StorageClass) VarDeclBits.SClassAsWritten; + } void setStorageClass(StorageClass SC); + void setStorageClassAsWritten(StorageClass SC) { + assert(isLegalForVariable(SC)); + VarDeclBits.SClassAsWritten = SC; + } void setThreadSpecified(bool T) { VarDeclBits.ThreadSpecified = T; } bool isThreadSpecified() const { @@ -797,6 +805,13 @@ public: getStorageClass() == SC_PrivateExtern; } + /// \brief Returns true if a variable was written with extern or + /// __private_extern__ storage. + bool hasExternalStorageAsWritten() const { + return getStorageClassAsWritten() == SC_Extern || + getStorageClassAsWritten() == SC_PrivateExtern; + } + /// hasGlobalStorage - Returns true for all variables that do not /// have local storage. This includs all global variables as well /// as static variables declared within a function. @@ -1130,7 +1145,7 @@ public: ImplicitParamDecl(DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType Type) : VarDecl(ImplicitParam, DC, IdLoc, IdLoc, Id, Type, - /*tinfo*/ 0, SC_None) { + /*tinfo*/ 0, SC_None, SC_None) { setImplicit(); } @@ -1149,8 +1164,8 @@ protected: ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, Expr *DefArg) - : VarDecl(DK, DC, StartLoc, IdLoc, Id, T, TInfo, S) { + StorageClass S, StorageClass SCAsWritten, Expr *DefArg) + : VarDecl(DK, DC, StartLoc, IdLoc, Id, T, TInfo, S, SCAsWritten) { assert(ParmVarDeclBits.HasInheritedDefaultArg == false); assert(ParmVarDeclBits.IsKNRPromoted == false); assert(ParmVarDeclBits.IsObjCMethodParam == false); @@ -1162,7 +1177,8 @@ public: SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, Expr *DefArg); + StorageClass S, StorageClass SCAsWritten, + Expr *DefArg); static ParmVarDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -1367,6 +1383,7 @@ private: // FIXME: This can be packed into the bitfields in Decl. // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum unsigned SClass : 2; + unsigned SClassAsWritten : 2; bool IsInline : 1; bool IsInlineSpecified : 1; bool IsVirtualAsWritten : 1; @@ -1456,13 +1473,13 @@ protected: FunctionDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass S, bool isInlineSpecified, + StorageClass S, StorageClass SCAsWritten, bool isInlineSpecified, bool isConstexprSpecified) : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, StartLoc), DeclContext(DK), ParamInfo(0), Body(), - SClass(S), + SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), @@ -1494,12 +1511,13 @@ public: DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, + StorageClass SCAsWritten, bool isInlineSpecified = false, bool hasWrittenPrototype = true, bool isConstexprSpecified = false) { DeclarationNameInfo NameInfo(N, NLoc); return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, - SC, + SC, SCAsWritten, isInlineSpecified, hasWrittenPrototype, isConstexprSpecified); } @@ -1509,6 +1527,7 @@ public: const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, + StorageClass SCAsWritten, bool isInlineSpecified, bool hasWrittenPrototype, bool isConstexprSpecified = false); @@ -1760,9 +1779,12 @@ public: return getType()->getAs<FunctionType>()->getCallResultType(getASTContext()); } - /// \brief Returns the storage class as written in the source. For the - /// computed linkage of symbol, see getLinkage. StorageClass getStorageClass() const { return StorageClass(SClass); } + void setStorageClass(StorageClass SC); + + StorageClass getStorageClassAsWritten() const { + return StorageClass(SClassAsWritten); + } /// \brief Determine whether the "inline" keyword was specified for this /// function. diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 05ff49c64c..430e6d8cc5 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1573,10 +1573,11 @@ protected: CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass SC, bool isInline, + bool isStatic, StorageClass SCAsWritten, bool isInline, bool isConstexpr, SourceLocation EndLocation) : FunctionDecl(DK, RD, StartLoc, NameInfo, T, TInfo, - SC, isInline, isConstexpr) { + (isStatic ? SC_Static : SC_None), + SCAsWritten, isInline, isConstexpr) { if (EndLocation.isValid()) setRangeEnd(EndLocation); } @@ -1586,14 +1587,15 @@ public: SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass SC, + bool isStatic, + StorageClass SCAsWritten, bool isInline, bool isConstexpr, SourceLocation EndLocation); static CXXMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - bool isStatic() const; + + bool isStatic() const { return getStorageClass() == SC_Static; } bool isInstance() const { return !isStatic(); } bool isConst() const { return getType()->castAs<FunctionType>()->isConst(); } @@ -2001,7 +2003,7 @@ class CXXConstructorDecl : public CXXMethodDecl { QualType T, TypeSourceInfo *TInfo, bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared, bool isConstexpr) - : CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, + : CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, false, SC_None, isInline, isConstexpr, SourceLocation()), IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), CtorInitializers(0), NumCtorInitializers(0) { @@ -2220,7 +2222,7 @@ class CXXDestructorDecl : public CXXMethodDecl { const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo, + : CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo, false, SC_None, isInline, /*isConstexpr=*/false, SourceLocation()), ImplicitlyDefined(false), OperatorDelete(0) { setImplicit(isImplicitlyDeclared); @@ -2287,7 +2289,7 @@ class CXXConversionDecl : public CXXMethodDecl { QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicitSpecified, bool isConstexpr, SourceLocation EndLocation) - : CXXMethodDecl(CXXConversion, RD, StartLoc, NameInfo, T, TInfo, + : CXXMethodDecl(CXXConversion, RD, StartLoc, NameInfo, T, TInfo, false, SC_None, isInline, isConstexpr, EndLocation), IsExplicitSpecified(isExplicitSpecified) { } diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 5b90784dcf..48cd4d14f8 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -338,6 +338,8 @@ private: // constexpr-specifier unsigned Constexpr_specified : 1; + /*SCS*/unsigned StorageClassSpecAsWritten : 3; + union { UnionParsedType TypeRep; Decl *DeclRep; @@ -376,6 +378,7 @@ private: WrittenBuiltinSpecs writtenBS; void SaveWrittenBuiltinSpecs(); + void SaveStorageSpecifierAsWritten(); ObjCDeclSpec *ObjCQualifiers; @@ -415,6 +418,7 @@ public: FS_noreturn_specified(false), Friend_specified(false), Constexpr_specified(false), + StorageClassSpecAsWritten(SCS_unspecified), Attrs(attrFactory), ProtocolQualifiers(0), NumProtocolQualifiers(0), @@ -549,6 +553,10 @@ public: /// DeclSpec includes. unsigned getParsedSpecifiers() const; + SCS getStorageClassSpecAsWritten() const { + return (SCS)StorageClassSpecAsWritten; + } + /// isEmpty - Return true if this declaration specifier is completely empty: /// no tokens were parsed in the production of it. bool isEmpty() const { diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index d17557260e..7b07352d3c 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1402,7 +1402,7 @@ public: ParmVarDecl *CheckParameter(DeclContext *DC, SourceLocation StartLoc, SourceLocation NameLoc, IdentifierInfo *Name, QualType T, TypeSourceInfo *TSInfo, - StorageClass SC); + StorageClass SC, StorageClass SCAsWritten); void ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, Expr *defarg); diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index b1d174b855..740153029b 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -749,7 +749,7 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { dumpName(D); dumpType(D->getType()); - StorageClass SC = D->getStorageClass(); + StorageClass SC = D->getStorageClassAsWritten(); if (SC != SC_None) OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); if (D->isInlineSpecified()) @@ -850,7 +850,7 @@ void ASTDumper::VisitFieldDecl(const FieldDecl *D) { void ASTDumper::VisitVarDecl(const VarDecl *D) { dumpName(D); dumpType(D->getType()); - StorageClass SC = D->getStorageClass(); + StorageClass SC = D->getStorageClassAsWritten(); if (SC != SC_None) OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); if (D->isThreadSpecified()) diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index d2e6d29705..01d1a1e917 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -2716,7 +2716,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { cast<CXXRecordDecl>(DC), D->getInnerLocStart(), NameInfo, T, TInfo, - Method->getStorageClass(), + Method->isStatic(), + Method->getStorageClassAsWritten(), Method->isInlineSpecified(), D->isConstexpr(), Importer.Import(D->getLocEnd())); @@ -2724,6 +2725,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction = FunctionDecl::Create(Importer.getToContext(), DC, D->getInnerLocStart(), NameInfo, T, TInfo, D->getStorageClass(), + D->getStorageClassAsWritten(), D->isInlineSpecified(), D->hasWrittenPrototype(), D->isConstexpr()); @@ -3074,7 +3076,8 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, - D->getStorageClass()); + D->getStorageClass(), + D->getStorageClassAsWritten()); ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc())); ToVar->setAccess(D->getAccess()); ToVar->setLexicalDeclContext(LexicalDC); @@ -3142,6 +3145,7 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getStorageClass(), + D->getStorageClassAsWritten(), /*FIXME: Default argument*/ 0); ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg()); return Importer.Imported(D, ToParm); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 9505d299ab..4b92069762 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -498,24 +498,26 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // declared to have external linkage; or (there is no equivalent in C99) if (Context.getLangOpts().CPlusPlus && Var->getType().isConstQualified() && - !Var->getType().isVolatileQualified()) { - const VarDecl *PrevVar = Var->getPreviousDecl(); - if (PrevVar) - return PrevVar->getLinkageAndVisibility(); - - if (Var->getStorageClass() != SC_Extern && - Var->getStorageClass() != SC_PrivateExtern) + !Var->getType().isVolatileQualified() && + Var->getStorageClass() != SC_Extern && + Var->getStorageClass() != SC_PrivateExtern) { + bool FoundExtern = false; + for (const VarDecl *PrevVar = Var->getPreviousDecl(); + PrevVar && !FoundExtern; + PrevVar = PrevVar->getPreviousDecl()) + if (isExternalLinkage(PrevVar->getLinkage())) + FoundExtern = true; + + if (!FoundExtern) return LinkageInfo::internal(); } - - for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar; - PrevVar = PrevVar->getPreviousDecl()) { - if (PrevVar->getStorageClass() == SC_PrivateExtern && - Var->getStorageClass() == SC_None) + if (Var->getStorageClass() == SC_None) { + const VarDecl *PrevVar = Var->getPreviousDecl(); + for (; PrevVar; PrevVar = PrevVar->getPreviousDecl()) + if (PrevVar->getStorageClass() == SC_PrivateExtern) + break; + if (PrevVar) return PrevVar->getLinkageAndVisibility(); - // Explicitly declared static. - if (PrevVar->getStorageClass() == SC_Static) - return LinkageInfo::internal(); } } else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) { // C++ [temp]p4: @@ -529,7 +531,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, Function = cast<FunctionDecl>(D); // Explicitly declared static. - if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) + if (Function->getStorageClass() == SC_Static) return LinkageInfo(InternalLinkage, DefaultVisibility, false); } else if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) { // - a data member of an anonymous union. @@ -993,7 +995,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D, return LinkageInfo::uniqueExternal(); // This is a "void f();" which got merged with a file static. - if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) + if (Function->getStorageClass() == SC_Static) return LinkageInfo::internal(); LinkageInfo LV; @@ -1011,11 +1013,15 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D, } if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { - if (Var->hasExternalStorage()) { + if (Var->hasExternalStorageAsWritten()) { if (Var->isInAnonymousNamespace() && !Var->getDeclContext()->isExternCContext()) return LinkageInfo::uniqueExternal(); + // This is an "extern int foo;" which got merged with a file static. + if (Var->getStorageClass() == SC_Static) + return LinkageInfo::internal(); + LinkageInfo LV; if (Var->getStorageClass() == SC_PrivateExtern) LV.mergeVisibility(HiddenVisibility, true); @@ -1024,13 +1030,9 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D, LV.mergeVisibility(*Vis, true); } - if (const VarDecl *Prev = Var->getPreviousDecl()) { - LinkageInfo PrevLV = getLVForDecl(Prev, computation); - if (PrevLV.getLinkage()) - LV.setLinkage(PrevLV.getLinkage()); - LV.mergeVisibility(PrevLV); - } - + // Note that Sema::MergeVarDecl already takes care of implementing + // C99 6.2.2p4 and propagating the visibility attribute, so we don't + // have to do it here. return LV; } } @@ -1465,18 +1467,21 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartL, SourceLocation IdL, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S) { - return new (C) VarDecl(Var, DC, StartL, IdL, Id, T, TInfo, S); + StorageClass S, StorageClass SCAsWritten) { + return new (C) VarDecl(Var, DC, StartL, IdL, Id, T, TInfo, S, SCAsWritten); } VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(VarDecl)); return new (Mem) VarDecl(Var, 0, SourceLocation(), SourceLocation(), 0, - QualType(), 0, SC_None); + QualType(), 0, SC_None, SC_None); } void VarDecl::setStorageClass(StorageClass SC) { assert(isLegalForVariable(SC)); + if (getStorageClass() != SC) + assert(isLinkageValid()); + VarDeclBits.SClass = SC; } @@ -1576,7 +1581,7 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( if (hasExternalStorage()) return DeclarationOnly; - if (hasExternalStorage()) { + if (hasExternalStorageAsWritten()) { for (const VarDecl *PrevVar = getPreviousDecl(); PrevVar; PrevVar = PrevVar->getPreviousDecl()) { if (PrevVar->getLinkage() == InternalLinkage) @@ -1874,15 +1879,16 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, Expr *DefArg) { + StorageClass S, StorageClass SCAsWritten, + Expr *DefArg) { return new (C) ParmVarDecl(ParmVar, DC, StartLoc, IdLoc, Id, T, TInfo, - S, DefArg); + S, SCAsWritten, DefArg); } ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ParmVarDecl)); return new (Mem) ParmVarDecl(ParmVar, 0, SourceLocation(), SourceLocation(), - 0, QualType(), 0, SC_None, 0); + 0, QualType(), 0, SC_None, SC_None, 0); } SourceRange ParmVarDecl::getSourceRange() const { @@ -2061,7 +2067,7 @@ bool FunctionDecl::isGlobal() const { if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this)) return Method->isStatic(); - if (getCanonicalDecl()->getStorageClass() == SC_Static) + if (getStorageClass() == SC_Static) return false; for (const DeclContext *DC = getDeclContext(); @@ -2106,6 +2112,14 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDeclaration(); } +void FunctionDecl::setStorageClass(StorageClass SC) { + assert(isLegalForFunction(SC)); + if (getStorageClass() != SC) + assert(isLinkageValid()); + + SClass = SC; +} + /// \brief Returns a value indicating whether this function /// corresponds to a builtin function. /// @@ -2256,7 +2270,7 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { // // FIXME: What happens if gnu_inline gets added on after the first // declaration? - if (!isInlineSpecified() || getStorageClass() == SC_Extern) + if (!isInlineSpecified() || getStorageClassAsWritten() == SC_Extern) return false; const FunctionDecl *Prev = this; @@ -2268,10 +2282,10 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { // If it's not the case that both 'inline' and 'extern' are // specified on the definition, then it is always externally visible. if (!Prev->isInlineSpecified() || - Prev->getStorageClass() != SC_Extern) + Prev->getStorageClassAsWritten() != SC_Extern) return false; } else if (Prev->isInlineSpecified() && - Prev->getStorageClass() != SC_Extern) { + Prev->getStorageClassAsWritten() != SC_Extern) { return false; } } @@ -2326,7 +2340,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { // If it's not the case that both 'inline' and 'extern' are // specified on the definition, then this inline definition is // externally visible. - if (!(isInlineSpecified() && getStorageClass() == SC_Extern)) + if (!(isInlineSpecified() && getStorageClassAsWritten() == SC_Extern)) return true; // If any declaration is 'inline' but not 'extern', then this definition @@ -2335,7 +2349,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { Redecl != RedeclEnd; ++Redecl) { if (Redecl->isInlineSpecified() && - Redecl->getStorageClass() != SC_Extern) + Redecl->getStorageClassAsWritten() != SC_Extern) return true; } @@ -3198,12 +3212,12 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass SC, + StorageClass SC, StorageClass SCAsWritten, bool isInlineSpecified, bool hasWrittenPrototype, bool isConstexprSpecified) { FunctionDecl *New = new (C) FunctionDecl(Function, DC, StartLoc, NameInfo, - T, TInfo, SC, + T, TInfo, SC, SCAsWritten, isInlineSpecified, isConstexprSpecified); New->HasWrittenPrototype = hasWrittenPrototype; @@ -3214,7 +3228,7 @@ FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FunctionDecl)); return new (Mem) FunctionDecl(Function, 0, SourceLocation(), DeclarationNameInfo(), QualType(), 0, - SC_None, false, false); + SC_None, SC_None, false, false); } BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index bd6d99cd59..1e60560485 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -435,7 +435,7 @@ bool Decl::canBeWeakImported(bool &IsDefinition) const { // Variables, if they aren't definitions. if (const VarDecl *Var = dyn_cast<VarDecl>(this)) { - if (Var->isThisDeclarationADefinition()) { + if (!Var->hasExternalStorage() || Var->getInit()) { IsDefinition = true; return false; } |