aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2013-04-03 19:22:20 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2013-04-03 19:22:20 +0000
commit4f8a3eb2ce5d4ba422483439e20c8cbb4d953a41 (patch)
treeda183dd16cf78a8e3e464f1e041cd33f425ab580
parentf9f30791dd20472675de012105219cd975ad1076 (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
-rw-r--r--docs/ReleaseNotes.rst11
-rw-r--r--include/clang/AST/Decl.h48
-rw-r--r--include/clang/AST/DeclCXX.h18
-rw-r--r--include/clang/Sema/DeclSpec.h8
-rw-r--r--include/clang/Sema/Sema.h2
-rw-r--r--lib/AST/ASTDumper.cpp4
-rw-r--r--lib/AST/ASTImporter.cpp8
-rw-r--r--lib/AST/Decl.cpp96
-rw-r--r--lib/AST/DeclBase.cpp2
-rw-r--r--lib/AST/DeclCXX.cpp42
-rw-r--r--lib/AST/DeclPrinter.cpp8
-rw-r--r--lib/CodeGen/CGBlocks.cpp4
-rw-r--r--lib/CodeGen/CGDecl.cpp2
-rw-r--r--lib/CodeGen/CGObjC.cpp2
-rw-r--r--lib/CodeGen/CodeGenModule.cpp2
-rw-r--r--lib/Rewrite/Frontend/RewriteModernObjC.cpp34
-rw-r--r--lib/Rewrite/Frontend/RewriteObjC.cpp28
-rw-r--r--lib/Sema/DeclSpec.cpp12
-rw-r--r--lib/Sema/Sema.cpp2
-rw-r--r--lib/Sema/SemaCodeComplete.cpp2
-rw-r--r--lib/Sema/SemaDecl.cpp124
-rw-r--r--lib/Sema/SemaDeclAttr.cpp6
-rw-r--r--lib/Sema/SemaDeclCXX.cpp20
-rw-r--r--lib/Sema/SemaDeclObjC.cpp4
-rw-r--r--lib/Sema/SemaExpr.cpp4
-rw-r--r--lib/Sema/SemaExprCXX.cpp5
-rw-r--r--lib/Sema/SemaExprObjC.cpp19
-rw-r--r--lib/Sema/SemaLambda.cpp7
-rw-r--r--lib/Sema/SemaObjCProperty.cpp1
-rw-r--r--lib/Sema/SemaPseudoObject.cpp3
-rw-r--r--lib/Sema/SemaStmt.cpp2
-rw-r--r--lib/Sema/SemaTemplate.cpp3
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp3
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp8
-rw-r--r--lib/Sema/SemaType.cpp2
-rw-r--r--lib/Sema/TreeTransform.h1
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp6
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp6
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;
}
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index ffad9ae93c..9ed9b7d363 100644
--- a/