summaryrefslogtreecommitdiff
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)
downloadclang-4f8a3eb2ce5d4ba422483439e20c8cbb4d953a41.tar.gz
clang-4f8a3eb2ce5d4ba422483439e20c8cbb4d953a41.tar.bz2
clang-4f8a3eb2ce5d4ba422483439e20c8cbb4d953a41.tar.xz
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/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -1251,42 +1251,6 @@ bool CXXRecordDecl::mayBeAbstract() const {
void CXXMethodDecl::anchor() { }
-bool CXXMethodDecl::isStatic() const {
- const CXXMethodDecl *MD = this;
- for (;;) {
- const CXXMethodDecl *C = MD->getCanonicalDecl();
- if (C != MD) {
- MD = C;
- continue;
- }
-
- FunctionTemplateSpecializationInfo *Info =
- MD->getTemplateSpecializationInfo();
- if (!Info)
- break;
- MD = cast<CXXMethodDecl>(Info->getTemplate()->getTemplatedDecl());
- }
-
- if (MD->getStorageClass() == SC_Static)
- return true;
-
- DeclarationName Name = getDeclName();
- // [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)
- return 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)
- return true;
-
- return false;
-}
-
static bool recursivelyOverrides(const CXXMethodDecl *DerivedMD,
const CXXMethodDecl *BaseMD) {
for (CXXMethodDecl::method_iterator I = DerivedMD->begin_overridden_methods(),
@@ -1348,10 +1312,10 @@ CXXMethodDecl::Create(ASTContext &C, 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) {
return new (C) CXXMethodDecl(CXXMethod, RD, StartLoc, NameInfo, T, TInfo,
- SC, isInline, isConstexpr,
+ isStatic, SCAsWritten, isInline, isConstexpr,
EndLocation);
}
@@ -1359,7 +1323,7 @@ CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXMethodDecl));
return new (Mem) CXXMethodDecl(CXXMethod, 0, SourceLocation(),
DeclarationNameInfo(), QualType(),
- 0, SC_None, false, false,
+ 0, false, SC_None, false, false,
SourceLocation());
}
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index c3bf8f89b2..54fa9ca589 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -393,7 +393,7 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
if (!Policy.SuppressSpecifiers) {
- switch (D->getStorageClass()) {
+ switch (D->getStorageClassAsWritten()) {
case SC_None: break;
case SC_Extern: Out << "extern "; break;
case SC_Static: Out << "static "; break;
@@ -641,9 +641,9 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
void DeclPrinter::VisitVarDecl(VarDecl *D) {
- StorageClass SC = D->getStorageClass();
- if (!Policy.SuppressSpecifiers && SC != SC_None)
- Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
+ StorageClass SCAsWritten = D->getStorageClassAsWritten();
+ if (!Policy.SuppressSpecifiers && SCAsWritten != SC_None)
+ Out << VarDecl::getStorageClassSpecifierString(SCAsWritten) << " ";
if (!Policy.SuppressSpecifiers && D->isThreadSpecified())
Out << "__thread ";
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 227ee2d024..374c824a20 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -1316,6 +1316,7 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
SourceLocation(),
SourceLocation(), II, C.VoidTy, 0,
SC_Static,
+ SC_None,
false,
false);
StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation());
@@ -1490,6 +1491,7 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
SourceLocation(),
SourceLocation(), II, C.VoidTy, 0,
SC_Static,
+ SC_None,
false, false);
StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation());
@@ -1780,6 +1782,7 @@ generateByrefCopyHelper(CodeGenFunction &CGF,
SourceLocation(),
SourceLocation(), II, R, 0,
SC_Static,
+ SC_None,
false, false);
// Initialize debug info if necessary.
@@ -1854,6 +1857,7 @@ generateByrefDisposeHelper(CodeGenFunction &CGF,
SourceLocation(),
SourceLocation(), II, R, 0,
SC_Static,
+ SC_None,
false, false);
// Initialize debug info if necessary.
CGF.maybeInitializeDebugInfo();
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 5375c5e18f..1255e654dc 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -109,7 +109,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
/// EmitVarDecl - This method handles emission of any variable declaration
/// inside a function, including static vars etc.
void CodeGenFunction::EmitVarDecl(const VarDecl &D) {
- switch (D.getStorageClass()) {
+ switch (D.getStorageClassAsWritten()) {
case SC_None:
case SC_Auto:
case SC_Register:
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 2e3bd5f7f1..e8378becf1 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -2848,6 +2848,7 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
SourceLocation(),
SourceLocation(), II, C.VoidTy, 0,
SC_Static,
+ SC_None,
false,
false);
@@ -2932,6 +2933,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
SourceLocation(),
SourceLocation(), II, C.VoidTy, 0,
SC_Static,
+ SC_None,
false,
false);
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 6d85a8835b..9f604e860e 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1602,7 +1602,7 @@ CodeGenModule::MaybeEmitGlobalStdInitializerListInitializer(const VarDecl *D,
D->getDeclContext()),
D->getLocStart(), D->getLocation(),
name, arrayType, sourceInfo,
- SC_Static);
+ SC_Static, SC_Static);
// Now clone the InitListExpr to initialize the array instead.
// Incredible hack: we want to use the existing InitListExpr here, so we need
diff --git a/lib/Rewrite/Frontend/RewriteModernObjC.cpp b/lib/Rewrite/Frontend/RewriteModernObjC.cpp
index 0e59b113c9..c05e8a6d69 100644
--- a/lib/Rewrite/Frontend/RewriteModernObjC.cpp
+++ b/lib/Rewrite/Frontend/RewriteModernObjC.cpp
@@ -2365,7 +2365,7 @@ void RewriteModernObjC::SynthSelGetUidFunctionDecl() {
SourceLocation(),
SourceLocation(),
SelGetUidIdent, getFuncType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
void RewriteModernObjC::RewriteFunctionDecl(FunctionDecl *FD) {
@@ -2463,7 +2463,7 @@ void RewriteModernObjC::SynthSuperContructorFunctionDecl() {
SourceLocation(),
SourceLocation(),
msgSendIdent, msgSendType,
- 0, SC_Extern);
+ 0, SC_Extern, SC_None);
}
// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
@@ -2482,7 +2482,7 @@ void RewriteModernObjC::SynthMsgSendFunctionDecl() {
SourceLocation(),
SourceLocation(),
msgSendIdent, msgSendType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(void);
@@ -2496,7 +2496,7 @@ void RewriteModernObjC::SynthMsgSendSuperFunctionDecl() {
SourceLocation(),
SourceLocation(),
msgSendIdent, msgSendType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
@@ -2515,7 +2515,7 @@ void RewriteModernObjC::SynthMsgSendStretFunctionDecl() {
SourceLocation(),
SourceLocation(),
msgSendIdent, msgSendType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
// SynthMsgSendSuperStretFunctionDecl -
@@ -2532,7 +2532,7 @@ void RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() {
SourceLocation(),
msgSendIdent,
msgSendType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
@@ -2551,7 +2551,7 @@ void RewriteModernObjC::SynthMsgSendFpretFunctionDecl() {
SourceLocation(),
SourceLocation(),
msgSendIdent, msgSendType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
// SynthGetClassFunctionDecl - Class objc_getClass(const char *name);
@@ -2565,7 +2565,7 @@ void RewriteModernObjC::SynthGetClassFunctionDecl() {
SourceLocation(),
SourceLocation(),
getClassIdent, getClassType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
@@ -2581,7 +2581,7 @@ void RewriteModernObjC::SynthGetSuperClassFunctionDecl() {
SourceLocation(),
getSuperClassIdent,
getClassType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
// SynthGetMetaClassFunctionDecl - Class objc_getMetaClass(const char *name);
@@ -2595,7 +2595,7 @@ void RewriteModernObjC::SynthGetMetaClassFunctionDecl() {
SourceLocation(),
SourceLocation(),
getClassIdent, getClassType,
- 0, SC_Extern);
+ 0, SC_Extern, SC_None);
}
Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
@@ -2628,7 +2628,7 @@ Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), &Context->Idents.get(S),
- strType, 0, SC_Static);
+ strType, 0, SC_Static, SC_None);
DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, strType, VK_LValue,
SourceLocation());
Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf,
@@ -3139,7 +3139,7 @@ static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R,
if (!LSD->getRBraceLoc().isValid())
return LSD->getExternLoc();
}
- if (FD->getStorageClass() != SC_None)
+ if (FD->getStorageClassAsWritten() != SC_None)
R.RewriteBlockLiteralFunctionDecl(FD);
return FD->getTypeSpecStartLoc();
}
@@ -3250,7 +3250,7 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla
IdentifierInfo *ID = &Context->Idents.get(name);
FunctionDecl *FD = FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), ID, castType, 0,
- SC_Extern, false, false);
+ SC_Extern, SC_None, false, false);
DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, castType, VK_RValue,
SourceLocation());
CallExpr *STCE = new (Context) CallExpr(*Context, DRE, MsgExprs,
@@ -3723,7 +3723,7 @@ Stmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
IdentifierInfo *ID = &Context->Idents.get(Name);
VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), ID, getProtocolType(), 0,
- SC_Extern);
+ SC_Extern, SC_None);
DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, false, getProtocolType(),
VK_LValue, SourceLocation());
Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf,
@@ -5403,7 +5403,7 @@ FunctionDecl *RewriteModernObjC::SynthBlockInitFunctionDecl(StringRef name) {
QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), ID, FType, 0, SC_Extern,
- false, false);
+ SC_None, false, false);
}
Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
@@ -5504,7 +5504,7 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
SourceLocation(), SourceLocation(),
&Context->Idents.get(DescData.c_str()),
Context->VoidPtrTy, 0,
- SC_Static);
+ SC_Static, SC_None);
UnaryOperator *DescRefExpr =
new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false,
Context->VoidPtrTy,
@@ -7768,7 +7768,7 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
BaseExpr);
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), &Context->Idents.get(IvarOffsetName),
- Context->UnsignedLongTy, 0, SC_Extern);
+ Context->UnsignedLongTy, 0, SC_Extern, SC_None);
DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false,
Context->UnsignedLongTy, VK_LValue,
SourceLocation());
diff --git a/lib/Rewrite/Frontend/RewriteObjC.cpp b/lib/Rewrite/Frontend/RewriteObjC.cpp
index 2f5cd0f6c6..108041753d 100644
--- a/lib/Rewrite/Frontend/RewriteObjC.cpp
+++ b/lib/Rewrite/Frontend/RewriteObjC.cpp
@@ -2267,7 +2267,7 @@ void RewriteObjC::SynthSelGetUidFunctionDecl() {
SourceLocation(),
SourceLocation(),
SelGetUidIdent, getFuncType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) {
@@ -2363,7 +2363,7 @@ void RewriteObjC::SynthSuperContructorFunctionDecl() {
SourceLocation(),
SourceLocation(),
msgSendIdent, msgSendType,
- 0, SC_Extern);
+ 0, SC_Extern, SC_None);
}
// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
@@ -2382,7 +2382,7 @@ void RewriteObjC::SynthMsgSendFunctionDecl() {
SourceLocation(),
SourceLocation(),
msgSendIdent, msgSendType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
@@ -2404,7 +2404,7 @@ void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
SourceLocation(),
SourceLocation(),
msgSendIdent, msgSendType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
@@ -2423,7 +2423,7 @@ void RewriteObjC::SynthMsgSendStretFunctionDecl() {
SourceLocation(),
SourceLocation(),
msgSendIdent, msgSendType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
// SynthMsgSendSuperStretFunctionDecl -
@@ -2448,7 +2448,7 @@ void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
SourceLocation(),
msgSendIdent,
msgSendType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
@@ -2467,7 +2467,7 @@ void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
SourceLocation(),
SourceLocation(),
msgSendIdent, msgSendType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
// SynthGetClassFunctionDecl - id objc_getClass(const char *name);
@@ -2481,7 +2481,7 @@ void RewriteObjC::SynthGetClassFunctionDecl() {
SourceLocation(),
SourceLocation(),
getClassIdent, getClassType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
@@ -2497,7 +2497,7 @@ void RewriteObjC::SynthGetSuperClassFunctionDecl() {
SourceLocation(),
getSuperClassIdent,
getClassType, 0,
- SC_Extern);
+ SC_Extern, SC_None);
}
// SynthGetMetaClassFunctionDecl - id objc_getMetaClass(const char *name);
@@ -2511,7 +2511,7 @@ void RewriteObjC::SynthGetMetaClassFunctionDecl() {
SourceLocation(),
SourceLocation(),
getClassIdent, getClassType,
- 0, SC_Extern);
+ 0, SC_Extern, SC_None);
}
Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
@@ -2544,7 +2544,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), &Context->Idents.get(S),
- strType, 0, SC_Static);
+ strType, 0, SC_Static, SC_None);
DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, strType, VK_LValue,
SourceLocation());
Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf,
@@ -3112,7 +3112,7 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
IdentifierInfo *ID = &Context->Idents.get(Name);
VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), ID, getProtocolType(), 0,
- SC_Extern);
+ SC_Extern, SC_None);
DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, false, getProtocolType(),
VK_LValue, SourceLocation());
Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf,
@@ -4448,7 +4448,7 @@ FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) {
QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), ID, FType, 0, SC_Extern,
- false, false);
+ SC_None, false, false);
}
Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
@@ -4532,7 +4532,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
SourceLocation(), SourceLocation(),
&Context->Idents.get(DescData.c_str()),
Context->VoidPtrTy, 0,
- SC_Static);
+ SC_Static, SC_None);
UnaryOperator *DescRefExpr =
new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false,
Context->VoidPtrTy,
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index e1d55dbddc..45f524b97b 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -815,6 +815,15 @@ void DeclSpec::SaveWrittenBuiltinSpecs() {
}
}
+void DeclSpec::SaveStorageSpecifierAsWritten() {
+ if (SCS_extern_in_linkage_spec && StorageClassSpec == SCS_extern)
+ // If 'extern' is part of a linkage specification,
+ // then it is not a storage class "as written".
+ StorageClassSpecAsWritten = SCS_unspecified;
+ else
+ StorageClassSpecAsWritten = StorageClassSpec;
+}
+
/// Finish - This does final analysis of the declspec, rejecting things like
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
@@ -822,6 +831,7 @@ void DeclSpec::SaveWrittenBuiltinSpecs() {
void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
// Before possibly changing their values, save specs as written.
SaveWrittenBuiltinSpecs();
+ SaveStorageSpecifierAsWritten();
// Check the type specifier components first.
@@ -931,7 +941,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().MicrosoftExt &&
TypeSpecType == TST_unspecified && StorageClassSpec == SCS_auto) {
TypeSpecType = TST_auto;
- StorageClassSpec = SCS_unspecified;
+ StorageClassSpec = StorageClassSpecAsWritten = SCS_unspecified;
TSTLoc = TSTNameLoc = StorageClassSpecLoc;
StorageClassSpecLoc = SourceLocation();
}
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 6bab9e80cb..8b17c123fd 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -728,7 +728,7 @@ void Sema::ActOnEndOfTranslationUnit() {
Diag(DiagD->getLocation(), diag::warn_unneeded_member_function)
<< DiagD->getDeclName();
else {
- if (FD->getStorageClass() == SC_Static &&
+ if (FD->getStorageClassAsWritten() == SC_Static &&
!FD->isInlineSpecified() &&
!SourceMgr.isFromMainFile(
SourceMgr.getExpansionLoc(FD->getLocation())))
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 2db1e2afa2..9c77e3f154 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -3349,7 +3349,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
// the initial opening bracket '[' missing. Add appropriate completions.
if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
DS.getTypeSpecType() == DeclSpec::TST_typename &&
- DS.getStorageClassSpec() == DeclSpec::SCS_unspecified &&
+ DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
!DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
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
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 982e7a5dd8..77c7dc59c8 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -5092,7 +5092,8 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
NewFD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),
Loc, Loc, DeclarationName(II),
FD->getType(), FD->getTypeSourceInfo(),
- SC_None, false/*isInlineSpecified*/,
+ SC_None, SC_None,
+ false/*isInlineSpecified*/,
FD->hasPrototype(),
false/*isConstexprSpecified*/);
NewD = NewFD;
@@ -5117,7 +5118,8 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
VD->getInnerLocStart(), VD->getLocation(), II,
VD->getType(), VD->getTypeSourceInfo(),
- VD->getStorageClass());
+ VD->getStorageClass(),
+ VD->getStorageClassAsWritten());
if (VD->getQualifier()) {
VarDecl *NewVD = cast<VarDecl>(NewD);
NewVD->setQualifierInfo(VD->getQualifierLoc());
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 35890e6deb..989edc6a45 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2852,7 +2852,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
= VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, Loc,
IterationVarName, SizeType,
SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc),
- SC_None);
+ SC_None, SC_None);
IndexVariables.push_back(IterationVar);
// Create a reference to the iteration variable.
@@ -7822,7 +7822,7 @@ void Sema::DeclareInheritingConstructors(CXXRecordDecl *ClassDecl) {
/*IdentifierInfo=*/0,
BaseCtorType->getArgType(i),
/*TInfo=*/0, SC_None,
- /*DefaultArg=*/0);
+ SC_None, /*DefaultArg=*/0);
PD->setScopeInfo(0, i);
PD->setImplicit();
ParamDecls.push_back(PD);
@@ -8275,7 +8275,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, Loc,
IterationVarName, SizeType,
S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
- SC_None);
+ SC_None, SC_None);
// Initialize the iteration variable to zero.
llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0);
@@ -8439,8 +8439,8 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXMethodDecl *CopyAssignment
= CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
- /*TInfo=*/0,
- /*StorageClass=*/SC_None,
+ /*TInfo=*/0, /*isStatic=*/false,
+ /*StorageClassAsWritten=*/SC_None,
/*isInline=*/true, /*isConstexpr=*/false,
SourceLocation());
CopyAssignment->setAccess(AS_public);
@@ -8457,6 +8457,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
ClassLoc, ClassLoc, /*Id=*/0,
ArgType, /*TInfo=*/0,
+ SC_None,
SC_None, 0);
CopyAssignment->setParams(FromParam);
@@ -8887,8 +8888,8 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXMethodDecl *MoveAssignment
= CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
- /*TInfo=*/0,
- /*StorageClass=*/SC_None,
+ /*TInfo=*/0, /*isStatic=*/false,
+ /*StorageClassAsWritten=*/SC_None,
/*isInline=*/true,
/*isConstexpr=*/false,
SourceLocation());
@@ -8906,6 +8907,7 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,
ClassLoc, ClassLoc, /*Id=*/0,
ArgType, /*TInfo=*/0,
+ SC_None,
SC_None, 0);
MoveAssignment->setParams(FromParam);
@@ -9260,6 +9262,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
ClassLoc, ClassLoc,
/*IdentifierInfo=*/0,
ArgType, /*TInfo=*/0,
+ SC_None,
SC_None, 0);
CopyConstructor->setParams(FromParam);
@@ -9446,6 +9449,7 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
ClassLoc, ClassLoc,
/*IdentifierInfo=*/0,
ArgType, /*TInfo=*/0,
+ SC_None,
SC_None, 0);
MoveConstructor->setParams(FromParam);
@@ -10277,7 +10281,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
}
VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name,
- ExDeclType, TInfo, SC_None);
+ ExDeclType, TInfo, SC_None, SC_None);
ExDecl->setExceptionVariable(true);
// In ARC, infer 'retaining' for variables of retainable type.
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 5d16f3eae6..1e2e4843ba 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -2930,7 +2930,7 @@ Decl *Sema::ActOnMethodDeclaration(
ParmVarDecl* Param = CheckParameter(ObjCMethod, StartLoc,
ArgInfo[i].NameLoc, ArgInfo[i].Name,
- ArgType, DI, SC_None);
+ ArgType, DI, SC_None, SC_None);
Param->setObjCMethodScopeInfo(i);
@@ -3161,7 +3161,7 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T,
}
VarDecl *New = VarDecl::Create(Context, CurContext, StartLoc, IdLoc, Id,
- T, TInfo, SC_None);
+ T, TInfo, SC_None, SC_None);
New->setExceptionVariable(true);
// In ARC, infer 'retaining' for variables of retainable type.
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index bcf5b78c34..5459d74016 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -162,7 +162,7 @@ static bool hasAnyExplicitStorageClass(const FunctionDecl *D) {
for (FunctionDecl::redecl_iterator I = D->redecls_begin(),
E = D->redecls_end();
I != E; ++I) {
- if (I->getStorageClass() != SC_None)
+ if (I->getStorageClassAsWritten() != SC_None)
return true;
}
return false;
@@ -10854,7 +10854,7 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
= VarDecl::Create(S.Context, S.CurContext, Loc, Loc,
IterationVarName, SizeType,
S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
- SC_None);
+ SC_None, SC_None);
IndexVariables.push_back(IterationVar);
LSI->ArrayIndexVars.push_back(IterationVar);
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 3f2cb02673..b586fd70b0 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1946,7 +1946,8 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
FunctionDecl *Alloc =
FunctionDecl::Create(Context, GlobalCtx, SourceLocation(),
SourceLocation(), Name,
- FnType, /*TInfo=*/0, SC_None, false, true);
+ FnType, /*TInfo=*/0, SC_None,
+ SC_None, false, true);
Alloc->setImplicit();
if (AddMallocAttr)
@@ -1955,7 +1956,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
SourceLocation(), 0,
Argument, /*TInfo=*/0,
- SC_None, 0);
+ SC_None, SC_None, 0);
Alloc->setParams(Param);
// FIXME: Also add this declaration to the IdentifierResolver, but
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 51a190651e..af8380df18 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -238,7 +238,7 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
SourceLocation(), SourceLocation(),
&CX.Idents.get("value"),
NumberType, /*TInfo=*/0, SC_None,
- 0);
+ SC_None, 0);
Method->setMethodParams(S.Context, value, ArrayRef<SourceLocation>());
}
@@ -489,7 +489,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
&Context.Idents.get("value"),
Context.getPointerType(ConstCharType),
/*TInfo=*/0,
- SC_None, 0);
+ SC_None, SC_None, 0);
M->setMethodParams(Context, value, ArrayRef<SourceLocation>());
BoxingMethod = M;
}
@@ -656,14 +656,16 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
SourceLocation(),
&Context.Idents.get("objects"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/0, SC_None, SC_None,
+ 0);
Params.push_back(objects);
ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("cnt"),
Context.UnsignedLongTy,
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/0, SC_None, SC_None,
+ 0);
Params.push_back(cnt);
Method->setMethodParams(Context, Params, ArrayRef<SourceLocation>());
}
@@ -772,21 +774,24 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
SourceLocation(),
&Context.Idents.get("objects"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/0, SC_None, SC_None,
+ 0);
Params.push_back(objects);
ParmVarDecl *keys = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("keys"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/0, SC_None, SC_None,
+ 0);
Params.push_back(keys);
ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("cnt"),
Context.UnsignedLongTy,
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/0, SC_None, SC_None,
+ 0);
Params.push_back(cnt);
Method->setMethodParams(Context, Params, ArrayRef<SourceLocation>());
}
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 53fa6dafdd..468fa0251e 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -74,6 +74,7 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
IntroducerRange.getBegin(),
MethodNameLoc),
MethodType->getType(), MethodType,
+ /*isStatic=*/false,
SC_None,
/*isInline=*/true,
/*isConstExpr=*/false,
@@ -737,7 +738,7 @@ static void addFunctionPointerConversion(Sema &S,
= CXXMethodDecl::Create(S.Context, Class, Loc,
DeclarationNameInfo(Name, Loc), FunctionTy,
CallOperator->getTypeSourceInfo(),
- SC_Static, /*IsInline=*/true,
+ /*IsStatic=*/true, SC_Static, /*IsInline=*/true,
/*IsConstexpr=*/false,
CallOperator->getBody()->getLocEnd());
SmallVector<ParmVarDecl *, 4> InvokeParams;
@@ -750,6 +751,7 @@ static void addFunctionPointerConversion(Sema &S,
From->getType(),
From->getTypeSourceInfo(),
From->getStorageClass(),
+ From->getStorageClassAsWritten(),
/*DefaultArg=*/0));
}
Invoke->setParams(InvokeParams);
@@ -1008,6 +1010,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
From->getType(),
From->getTypeSourceInfo(),
From->getStorageClass(),
+ From->getStorageClassAsWritten(),
/*DefaultArg=*/0));
}
Block->setParams(BlockParams);
@@ -1022,7 +1025,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
VarDecl *CapVar = VarDecl::Create(Context, Block, ConvLocation,
ConvLocation, 0,
Src->getType(), CapVarTSI,
- SC_None);
+ SC_None, SC_None);
BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false,
/*Nested=*/false, /*Copy=*/Init.take());
Block->setCaptures(Context, &Capture, &Capture + 1,
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 824a249084..7ad8bc722d 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -1973,6 +1973,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
property->getType().getUnqualifiedType(),
/*TInfo=*/0,
SC_None,
+ SC_None,
0);
SetterMethod->setMethodParams(Context, Argument,
ArrayRef<SourceLocation>());
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index b135507b1a..57706759f3 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -1087,6 +1087,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
: S.Context.getObjCIdType(),
/*TInfo=*/0,
SC_None,
+ SC_None,
0);
AtIndexGetter->setMethodParams(S.Context, Argument,
ArrayRef<SourceLocation>());
@@ -1201,6 +1202,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
S.Context.getObjCIdType(),
/*TInfo=*/0,
SC_None,
+ SC_None,
0);
Params.push_back(object);
ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,
@@ -1211,6 +1213,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
: S.Context.getObjCIdType(),
/*TInfo=*/0,
SC_None,
+ SC_None,
0);
Params.push_back(key);
AtIndexSetter->setMethodParams(S.Context, Params, ArrayRef<SourceLocation>());
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index ff1db821b6..a2dc616deb 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -1665,7 +1665,7 @@ VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc,
IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
VarDecl *Decl = VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type,
- TInfo, SC_None);
+ TInfo, SC_Auto, SC_None);
Decl->setImplicit();
return Decl;
}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 990626189e..adf25ce3ae 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -6057,7 +6057,8 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
TemplArgs, /*InsertPos=*/0,
SpecInfo->getTemplateSpecializationKind(),
ExplicitTemplateArgs);
-
+ FD->setStorageClass(Specialization->getStorageClass());
+
// The "previous declaration" for this function template specialization is
// the prior function template specialization.
Previous.clear();
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index f755b8ca45..255df80d66 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1682,7 +1682,8 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
OldParm->getLocation(),
OldParm->getIdentifier(),
NewDI->getType(), NewDI,
- OldParm->getStorageClass());
+ OldParm->getStorageClass(),
+ OldParm->getStorageClassAsWritten());
if (!NewParm)
return 0;
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 33e83d07d6..55725b603e 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -338,7 +338,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
D->getInnerLocStart(),
D->getLocation(), D->getIdentifier(),
DI->getType(), DI,
- D->getStorageClass());
+ D->getStorageClass(),
+ D->getStorageClassAsWritten());
Var->setThreadSpecified(D->isThreadSpecified());
Var->setInitStyle(D->getInitStyle());
Var->setCXXForRangeDecl(D->isCXXForRangeDecl());
@@ -1162,7 +1163,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
FunctionDecl *Function =
FunctionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),
D->getNameInfo(), T, TInfo,
- D->getStorageClass(),
+ D->getStorageClass(), D->getStorageClassAsWritten(),
D->isInlineSpecified(), D->hasWrittenPrototype(),
D->isConstexpr());
@@ -1528,7 +1529,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
} else {
Method = CXXMethodDecl::Create(SemaRef.Context, Record,
StartLoc, NameInfo, T, TInfo,
- D->getStorageClass(),
+ D->isStatic(),
+ D->getStorageClassAsWritten(),
D->isInlineSpecified(),
D->isConstexpr(), D->getLocEnd());
}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 7169eeab9b..136de7c221 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -2301,7 +2301,7 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
if (!D.isFunctionDeclarator() ||
D.getFunctionDefinitionKind() != FDK_Declaration ||
!S.CurContext->isFunctionOrMethod() ||
- D.getDeclSpec().getStorageClassSpec()
+ D.getDeclSpec().getStorageClassSpecAsWritten()
!= DeclSpec::SCS_unspecified)
return;
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index bdd68a7bde..e228d7a0f2 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -3994,6 +3994,7 @@ ParmVarDecl *TreeTransform<Derived>::TransformFunctionTypeParam(
NewDI->getType(),
NewDI,
OldParm->getStorageClass(),
+ OldParm->getStorageClassAsWritten(),
/* DefArg */ NULL);
newParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
OldParm->getFunctionScopeIndex() + indexAdjustment);
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 3dcae6fe6a..12114336b2 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -504,8 +504,9 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
// FunctionDecl's body is handled last at ASTDeclReader::Visit,
// after everything else is read.
-
+
FD->SClass = (StorageClass)Record[Idx++];
+ FD->SClassAsWritten = (StorageClass)Record[Idx++];
FD->IsInline = Record[Idx++];
FD->IsInlineSpecified = Record[Idx++];
FD->IsVirtualAsWritten = Record[Idx++];
@@ -893,8 +894,9 @@ void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {
void ASTDeclReader::VisitVarDecl(VarDecl *VD) {
RedeclarableResult Redecl = VisitRedeclarable(VD);
VisitDeclaratorDecl(VD);
-
+
VD->VarDeclBits.SClass = (StorageClass)Record[Idx++];
+ VD->VarDeclBits.SClassAsWritten = (StorageClass)Record[Idx++];
VD->VarDeclBits.ThreadSpecified = Record[Idx++];
VD->VarDeclBits.InitStyle = Record[Idx++];
VD->VarDeclBits.ExceptionVar = Record[Idx++];
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 023599d0db..1e1e12ee5a 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -319,6 +319,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
// after everything else is written.
Record.push_back(D->getStorageClass()); // FIXME: stable encoding
+ Record.push_back(D->getStorageClassAsWritten());
Record.push_back(D->IsInline);
Record.push_back(D->isInlineSpecified());
Record.push_back(D->isVirtualAsWritten());
@@ -676,7 +677,8 @@ void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
VisitRedeclarable(D);
VisitDeclaratorDecl(D);
- Record.push_back(D->getStorageClass());
+ Record.push_back(D->getStorageClass()); // FIXME: stable encoding
+ Record.push_back(D->getStorageClassAsWritten());
Record.push_back(D->isThreadSpecified());
Record.push_back(D->getInitStyle());
Record.push_back(D->isExceptionVariable());
@@ -1515,6 +1517,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
// VarDecl
Abv->Add(BitCodeAbbrevOp(0)); // StorageClass
+ Abv->Add(BitCodeAbbrevOp(0)); // StorageClassAsWritten
Abv->Add(BitCodeAbbrevOp(0)); // isThreadSpecified
Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer
Abv->Add(BitCodeAbbrevOp(0)); // isExceptionVariable
@@ -1594,6 +1597,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
// VarDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // StorageClass
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // StorageClassAsWritten
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isThreadSpecified
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // CXXDirectInitializer
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable