diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-10-10 14:49:18 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-10-10 14:49:18 +0000 |
commit | 147545d698972cfd34ece30a5d55e8180784161e (patch) | |
tree | 596d4b9451a02b67059816484b580445591c37f8 | |
parent | 25aaff9cf8a66bc236e5ccaf6183d11c14674cd3 (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.h | 3 | ||||
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 15 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 62 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 12 | ||||
-rw-r--r-- | test/SemaCXX/class.cpp | 4 |
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; +}; |