diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-07-01 19:46:12 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-07-01 19:46:12 +0000 |
commit | cd1c0555286ff5aec940802f27a46fd1bae8aee7 (patch) | |
tree | 8f6710ea14d2afb67546b41113b8930925f18fff | |
parent | 5a33687da07cb8ffc68ef5065ed46bab5c4d6555 (diff) | |
download | bcm5719-llvm-cd1c0555286ff5aec940802f27a46fd1bae8aee7.tar.gz bcm5719-llvm-cd1c0555286ff5aec940802f27a46fd1bae8aee7.zip |
Fix AST representations of alias-declarations which define tag types. Inside classes, the tag types need to have an associated access specifier, and inside function definitions, they need to be included in the declarations of the DeclStmt. These issues manifested as assertions during template instantiation, and also in a WIP constexpr patch.
llvm-svn: 134250
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 12 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 7 | ||||
-rw-r--r-- | clang/test/SemaTemplate/instantiate-function-2.cpp | 14 | ||||
-rw-r--r-- | clang/test/SemaTemplate/instantiate-member-class.cpp | 14 |
7 files changed, 63 insertions, 17 deletions
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 0b0946c0100..626ad5316d0 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1450,7 +1450,7 @@ bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), bool SuppressDeclarations = false); - void ParseSpecifierQualifierList(DeclSpec &DS); + void ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS = AS_none); void ParseObjCTypeQualifierList(ObjCDeclSpec &DS, ObjCTypeNameContext Context); @@ -1628,7 +1628,9 @@ bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, TypeResult ParseTypeName(SourceRange *Range = 0, Declarator::TheContext Context = Declarator::TypeNameContext, - ObjCDeclSpec *objcQuals = 0); + ObjCDeclSpec *objcQuals = 0, + AccessSpecifier AS = AS_none, + Decl **OwnedType = 0); void ParseBlockId(); void ProhibitAttributes(ParsedAttributesWithRange &attrs) { @@ -1778,7 +1780,8 @@ bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, Decl *ParseUsingDirectiveOrDeclaration(unsigned Context, const ParsedTemplateInfo &TemplateInfo, SourceLocation &DeclEnd, - ParsedAttributesWithRange &attrs); + ParsedAttributesWithRange &attrs, + Decl **OwnedType = 0); Decl *ParseUsingDirective(unsigned Context, SourceLocation UsingLoc, SourceLocation &DeclEnd, @@ -1787,7 +1790,8 @@ bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc, SourceLocation &DeclEnd, - AccessSpecifier AS = AS_none); + AccessSpecifier AS = AS_none, + Decl **OwnedType = 0); Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd); Decl *ParseNamespaceAlias(SourceLocation NamespaceLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 65ce34a7a2f..118130f8d94 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -839,7 +839,7 @@ public: // Symbol table / Decl tracking callbacks: SemaDecl.cpp. // - DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr); + DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = 0); void DiagnoseUseOfUnimplementedSelectors(); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 99441e0e0e3..3b08469ca1a 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -32,11 +32,15 @@ using namespace clang; /// Called type-id in C++. TypeResult Parser::ParseTypeName(SourceRange *Range, Declarator::TheContext Context, - ObjCDeclSpec *objcQuals) { + ObjCDeclSpec *objcQuals, + AccessSpecifier AS, + Decl **OwnedType) { // Parse the common declaration-specifiers piece. DeclSpec DS(AttrFactory); DS.setObjCQualifiers(objcQuals); - ParseSpecifierQualifierList(DS); + ParseSpecifierQualifierList(DS, AS); + if (OwnedType) + *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : 0; // Parse the abstract-declarator, if present. Declarator DeclaratorInfo(DS, Context); @@ -674,6 +678,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, ParenBraceBracketBalancer BalancerRAIIObj(*this); Decl *SingleDecl = 0; + Decl *OwnedType = 0; switch (Tok.getKind()) { case tok::kw_template: case tok::kw_export: @@ -696,7 +701,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, break; case tok::kw_using: SingleDecl = ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), - DeclEnd, attrs); + DeclEnd, attrs, &OwnedType); break; case tok::kw_static_assert: case tok::kw__Static_assert: @@ -708,8 +713,9 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, } // This routine returns a DeclGroup, if the thing we parsed only contains a - // single decl, convert it now. - return Actions.ConvertDeclToDeclGroup(SingleDecl); + // single decl, convert it now. Alias declarations can also declare a type; + // include that too if it is present. + return Actions.ConvertDeclToDeclGroup(SingleDecl, OwnedType); } /// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl] @@ -1081,10 +1087,10 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, /// type-qualifier specifier-qualifier-list[opt] /// [GNU] attributes specifier-qualifier-list[opt] /// -void Parser::ParseSpecifierQualifierList(DeclSpec &DS) { +void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS) { /// specifier-qualifier-list is a subset of declaration-specifiers. Just /// parse declaration-specifiers and complain about extra stuff. - ParseDeclarationSpecifiers(DS); + ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS); // Validate declspec for type-name. unsigned Specs = DS.getParsedSpecifiers(); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index b123461f1d5..d78f3728e1b 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -314,7 +314,8 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, const ParsedTemplateInfo &TemplateInfo, SourceLocation &DeclEnd, - ParsedAttributesWithRange &attrs) { + ParsedAttributesWithRange &attrs, + Decl **OwnedType) { assert(Tok.is(tok::kw_using) && "Not using token"); // Eat 'using'. @@ -342,7 +343,8 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, // Using declarations can't have attributes. ProhibitAttributes(attrs); - return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd); + return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd, + AS_none, OwnedType); } /// ParseUsingDirective - Parse C++ using-directive, assumes @@ -422,7 +424,8 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc, SourceLocation &DeclEnd, - AccessSpecifier AS) { + AccessSpecifier AS, + Decl **OwnedType) { CXXScopeSpec SS; SourceLocation TypenameLoc; bool IsTypeName; @@ -511,7 +514,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, TypeAlias = ParseTypeName(0, TemplateInfo.Kind ? Declarator::AliasTemplateContext : - Declarator::AliasDeclContext); + Declarator::AliasDeclContext, 0, AS, OwnedType); } else // Parse (optional) attributes (most likely GNU strong-using extension). MaybeParseGNUAttributes(attrs); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 8069eb43859..ad1a62eb7fc 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -45,7 +45,12 @@ using namespace clang; using namespace sema; -Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr) { +Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) { + if (OwnedType) { + Decl *Group[2] = { OwnedType, Ptr }; + return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, 2)); + } + return DeclGroupPtrTy::make(DeclGroupRef(Ptr)); } diff --git a/clang/test/SemaTemplate/instantiate-function-2.cpp b/clang/test/SemaTemplate/instantiate-function-2.cpp index b4c0d9d6393..21eccd49013 100644 --- a/clang/test/SemaTemplate/instantiate-function-2.cpp +++ b/clang/test/SemaTemplate/instantiate-function-2.cpp @@ -42,3 +42,17 @@ namespace PR9654 { f<int>(0); } } + +namespace AliasTagDef { + template<typename T> + T f() { + using S = struct { // expected-warning {{C++0x}} + T g() { + return T(); + } + }; + return S().g(); + } + + int n = f<int>(); +} diff --git a/clang/test/SemaTemplate/instantiate-member-class.cpp b/clang/test/SemaTemplate/instantiate-member-class.cpp index 74c2609dcd0..1028b45cc0e 100644 --- a/clang/test/SemaTemplate/instantiate-member-class.cpp +++ b/clang/test/SemaTemplate/instantiate-member-class.cpp @@ -104,3 +104,17 @@ namespace test2 { }; template class C<int>; } + +namespace AliasTagDef { + template<typename T> + struct F { + using S = struct U { // expected-warning {{C++0x}} + T g() { + return T(); + } + }; + }; + + int m = F<int>::S().g(); + int n = F<int>::U().g(); +} |