From 7509a2f5cc0dac9530ccbaf0194e7b17d88c6c99 Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Mon, 14 May 2018 19:36:45 +0000 Subject: [AST] Print correct tag decl for tag specifier For example, given: void fn() { struct T *p0; struct T { int i; } *p1; } -ast-print produced: void fn() { struct T { int i; } *p0; struct T { int i; } *p1; } Compiling that fails with a redefinition error. Given: void fn() { struct T *p0; struct __attribute__((deprecated)) T *p1; } -ast-print dropped the attribute. Details: For a tag specifier (that is, struct/union/class/enum used as a type specifier in a declaration) that was also a tag declaration (that is, first occurrence of the tag) or tag redeclaration (that is, later occurrence that specifies attributes or a member list), clang printed the tag specifier as either (1) the full tag definition if one existed, or (2) the first tag declaration otherwise. Redefinition errors were sometimes introduced, as in the first example above. Even when that was impossible because no member list was ever specified, attributes were sometimes lost, thus changing semantics and diagnostics, as in the second example above. This patch fixes a major culprit for these problems. It does so by creating an ElaboratedType with a new OwnedDecl member wherever an occurrence of a tag type is a (re)declaration of that tag type. PrintingPolicy's IncludeTagDefinition used to trigger printing of the member list, attributes, etc. for a tag specifier by using a tag (re)declaration selected as described above. Now, it triggers the same thing except it uses the tag (re)declaration stored in the OwnedDecl. Of course, other tooling can now make use of the new OwnedDecl as well. Also, to be more faithful to the original source, this patch suppresses printing of attributes inherited from previous declarations. Reviewed by: rsmith, aaron.ballman Differential Revision: https://reviews.llvm.org/D45463 llvm-svn: 332281 --- clang/lib/AST/ASTContext.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'clang/lib/AST/ASTContext.cpp') diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 5c64b94c40e..b59589791c3 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3979,12 +3979,12 @@ QualType ASTContext::getCanonicalTemplateSpecializationType( return QualType(Spec, 0); } -QualType -ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - QualType NamedType) const { +QualType ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + QualType NamedType, + TagDecl *OwnedTagDecl) const { llvm::FoldingSetNodeID ID; - ElaboratedType::Profile(ID, Keyword, NNS, NamedType); + ElaboratedType::Profile(ID, Keyword, NNS, NamedType, OwnedTagDecl); void *InsertPos = nullptr; ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -3999,7 +3999,8 @@ ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, (void)CheckT; } - T = new (*this, TypeAlignment) ElaboratedType(Keyword, NNS, NamedType, Canon); + T = new (*this, TypeAlignment) + ElaboratedType(Keyword, NNS, NamedType, Canon, OwnedTagDecl); Types.push_back(T); ElaboratedTypes.InsertNode(T, InsertPos); return QualType(T, 0); -- cgit v1.2.3