aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-10-10 14:49:18 +0000
committerDouglas Gregor <dgregor@apple.com>2011-10-10 14:49:18 +0000
commit147545d698972cfd34ece30a5d55e8180784161e (patch)
tree596d4b9451a02b67059816484b580445591c37f8
parent25aaff9cf8a66bc236e5ccaf6183d11c14674cd3 (diff)
Parse the initializer for a class member after handling its
declarator, so that the declarator is in scope for the initializer. Fixes PR9989. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141539 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Sema/Sema.h3
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp15
-rw-r--r--lib/Parse/ParseDeclCXX.cpp62
-rw-r--r--lib/Sema/SemaDeclCXX.cpp12
-rw-r--r--test/SemaCXX/class.cpp4
5 files changed, 54 insertions, 42 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index f462d5bc9d..96ce0daea1 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -3424,8 +3424,7 @@ public:
Declarator &D,
MultiTemplateParamsArg TemplateParameterLists,
Expr *BitfieldWidth, const VirtSpecifiers &VS,
- Expr *Init, bool HasDeferredInit,
- bool IsDefinition);
+ bool HasDeferredInit, bool IsDefinition);
void ActOnCXXInClassMemberInitializer(Decl *VarDecl, SourceLocation EqualLoc,
Expr *Init);
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 40e36f0a0b..ef7ad91cbc 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -35,15 +35,22 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
Decl *FnD;
if (D.getDeclSpec().isFriendSpecified())
- // FIXME: Friend templates
FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, true,
move(TemplateParams));
- else { // FIXME: pass template information through
+ else {
FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D,
move(TemplateParams), 0,
- VS, Init.release(),
- /*HasInit=*/false,
+ VS, /*HasInit=*/false,
/*IsDefinition*/true);
+ if (FnD) {
+ bool TypeSpecContainsAuto
+ = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
+ if (Init.get())
+ Actions.AddInitializerToDecl(FnD, Init.get(), false,
+ TypeSpecContainsAuto);
+ else
+ Actions.ActOnUninitializedDecl(FnD, TypeSpecContainsAuto);
+ }
}
HandleMemberFunctionDefaultArgs(D, FnD);
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 1ec6fcbaed..258c78bd34 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1714,7 +1714,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);
VirtSpecifiers VS;
- ExprResult Init;
// Hold late-parsed attributes so we can attach a Decl to them later.
LateParsedAttrList LateParsedAttrs;
@@ -1741,6 +1740,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// MSVC permits pure specifier on inline functions declared at class scope.
// Hence check for =0 before checking for function definition.
+ ExprResult Init;
if (getLang().MicrosoftExt && Tok.is(tok::equal) &&
DeclaratorInfo.isFunctionDeclarator() &&
NextToken().is(tok::numeric_constant)) {
@@ -1848,25 +1848,19 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// goes before or after the GNU attributes and __asm__.
ParseOptionalCXX0XVirtSpecifierSeq(VS);
+ bool HasInitializer = false;
bool HasDeferredInitializer = false;
if (Tok.is(tok::equal) || Tok.is(tok::l_brace)) {
if (BitfieldSize.get()) {
Diag(Tok, diag::err_bitfield_member_init);
SkipUntil(tok::comma, true, true);
} else {
+ HasInitializer = true;
HasDeferredInitializer = !DeclaratorInfo.isDeclarationOfFunction() &&
DeclaratorInfo.getDeclSpec().getStorageClassSpec()
!= DeclSpec::SCS_static &&
DeclaratorInfo.getDeclSpec().getStorageClassSpec()
!= DeclSpec::SCS_typedef;
-
- if (!HasDeferredInitializer) {
- SourceLocation EqualLoc;
- Init = ParseCXXMemberInitializer(
- DeclaratorInfo.isDeclarationOfFunction(), EqualLoc);
- if (Init.isInvalid())
- SkipUntil(tok::comma, true, true);
- }
}
}
@@ -1885,31 +1879,22 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
DeclaratorInfo,
move(TemplateParams),
BitfieldSize.release(),
- VS, Init.release(),
- HasDeferredInitializer,
+ VS, HasDeferredInitializer,
/*IsDefinition*/ false);
}
- if (ThisDecl)
- DeclsInGroup.push_back(ThisDecl);
-
- if (DeclaratorInfo.isFunctionDeclarator() &&
- DeclaratorInfo.getDeclSpec().getStorageClassSpec()
- != DeclSpec::SCS_typedef) {
- HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl);
- }
-
- DeclaratorInfo.complete(ThisDecl);
-
+
// Set the Decl for any late parsed attributes
for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {
LateParsedAttrs[i]->setDecl(ThisDecl);
}
LateParsedAttrs.clear();
+ // Handle the initializer.
if (HasDeferredInitializer) {
+ // The initializer was deferred; parse it and cache the tokens.
if (!getLang().CPlusPlus0x)
Diag(Tok, diag::warn_nonstatic_member_init_accepted_as_extension);
-
+
if (DeclaratorInfo.isArrayOfUnknownBound()) {
// C++0x [dcl.array]p3: An array bound may also be omitted when the
// declarator is followed by an initializer.
@@ -1922,8 +1907,36 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
ThisDecl->setInvalidDecl();
} else
ParseCXXNonStaticMemberInitializer(ThisDecl);
+ } else if (HasInitializer) {
+ // Normal initializer.
+ SourceLocation EqualLoc;
+ ExprResult Init
+ = ParseCXXMemberInitializer(DeclaratorInfo.isDeclarationOfFunction(),
+ EqualLoc);
+ if (Init.isInvalid())
+ SkipUntil(tok::comma, true, true);
+ else if (ThisDecl)
+ Actions.AddInitializerToDecl(ThisDecl, Init.get(), false,
+ DS.getTypeSpecType() == DeclSpec::TST_auto);
+ } else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static) {
+ // No initializer.
+ Actions.ActOnUninitializedDecl(ThisDecl,
+ DS.getTypeSpecType() == DeclSpec::TST_auto);
+ }
+
+ if (ThisDecl) {
+ Actions.FinalizeDeclaration(ThisDecl);
+ DeclsInGroup.push_back(ThisDecl);
+ }
+
+ if (DeclaratorInfo.isFunctionDeclarator() &&
+ DeclaratorInfo.getDeclSpec().getStorageClassSpec()
+ != DeclSpec::SCS_typedef) {
+ HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl);
}
+ DeclaratorInfo.complete(ThisDecl);
+
// If we don't have a comma, it is either the end of the list (a ';')
// or an error, bail out.
if (Tok.isNot(tok::comma))
@@ -1935,8 +1948,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Parse the next declarator.
DeclaratorInfo.clear();
VS.clear();
- BitfieldSize = 0;
- Init = 0;
+ BitfieldSize = true;
// Attributes are only allowed on the second declarator.
MaybeParseGNUAttributes(DeclaratorInfo);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index cce6a532fd..6c84c30663 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1428,7 +1428,7 @@ Decl *
Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
MultiTemplateParamsArg TemplateParameterLists,
Expr *BW, const VirtSpecifiers &VS,
- Expr *InitExpr, bool HasDeferredInit,
+ bool HasDeferredInit,
bool IsDefinition) {
const DeclSpec &DS = D.getDeclSpec();
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
@@ -1440,11 +1440,9 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Loc = D.getSourceRange().getBegin();
Expr *BitWidth = static_cast<Expr*>(BW);
- Expr *Init = static_cast<Expr*>(InitExpr);
assert(isa<CXXRecordDecl>(CurContext));
assert(!DS.isFriendSpecified());
- assert(!Init || !HasDeferredInit);
bool isFunc = D.isDeclarationOfFunction();
@@ -1609,14 +1607,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
assert((Name || isInstField) && "No identifier for non-field ?");
- if (Init)
- AddInitializerToDecl(Member, Init, false,
- DS.getTypeSpecType() == DeclSpec::TST_auto);
- else if (DS.getStorageClassSpec() == DeclSpec::SCS_static)
- ActOnUninitializedDecl(Member, DS.getTypeSpecType() == DeclSpec::TST_auto);
-
- FinalizeDeclaration(Member);
-
if (isInstField)
FieldCollector->Add(cast<FieldDecl>(Member));
return Member;
diff --git a/test/SemaCXX/class.cpp b/test/SemaCXX/class.cpp
index 8d1257895f..52b062b5a7 100644
--- a/test/SemaCXX/class.cpp
+++ b/test/SemaCXX/class.cpp
@@ -189,3 +189,7 @@ void f() {
S::c; // expected-error {{invalid use of nonstatic data member}}
}
}
+
+struct PR9989 {
+ static int const PR9989_Member = sizeof PR9989_Member;
+};