diff options
author | Joel E. Denny <jdenny.ornl@gmail.com> | 2018-05-15 00:44:14 +0000 |
---|---|---|
committer | Joel E. Denny <jdenny.ornl@gmail.com> | 2018-05-15 00:44:14 +0000 |
commit | ae7c9443559ac420a6f401b7a24eb2fcea8ba3e8 (patch) | |
tree | 0d39e1c0e8dc0762c0855ef2b693cbe2d3db40ba /clang/lib | |
parent | 980d93d0e0940fedb50906f7f31564fe24d2bded (diff) | |
download | bcm5719-llvm-ae7c9443559ac420a6f401b7a24eb2fcea8ba3e8.tar.gz bcm5719-llvm-ae7c9443559ac420a6f401b7a24eb2fcea8ba3e8.zip |
[AST] Fix printing tag decl groups in decl contexts
For example, given:
struct T1 {
struct T2 *p0;
};
-ast-print produced:
struct T1 {
struct T2;
struct T2 *p0;
};
Compiling that produces a warning that the first struct T2 declaration
does not declare anything.
Details:
A tag decl group is one or more decls that share a type specifier that
is a tag decl (that is, a struct/union/class/enum decl). Within
functions, the parser builds such a tag decl group as part of a
DeclStmt. However, in decl contexts, such as file scope or a member
list, the parser does not group together the members of a tag decl
group. Previously, detection of tag decl groups during printing was
implemented but only if the tag decl was unnamed. Otherwise, as in
the above example, the members of the group did not print together and
so sometimes introduced warnings.
This patch extends detection of tag decl groups in decl contexts to
any tag decl that is recorded in the AST as not free-standing.
Reviewed by: rsmith
Differential Revision: https://reviews.llvm.org/D45465
llvm-svn: 332314
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/DeclPrinter.cpp | 24 |
1 files changed, 13 insertions, 11 deletions
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 84c56e3b960..b60efe81043 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -375,21 +375,23 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { !isa<ClassTemplateSpecializationDecl>(DC)) continue; - // The next bits of code handles stuff like "struct {int x;} a,b"; we're + // The next bits of code handle stuff like "struct {int x;} a,b"; we're // forced to merge the declarations because there's no other way to - // refer to the struct in question. This limited merging is safe without - // a bunch of other checks because it only merges declarations directly - // referring to the tag, not typedefs. + // refer to the struct in question. When that struct is named instead, we + // also need to merge to avoid splitting off a stand-alone struct + // declaration that produces the warning ext_no_declarators in some + // contexts. + // + // This limited merging is safe without a bunch of other checks because it + // only merges declarations directly referring to the tag, not typedefs. // // Check whether the current declaration should be grouped with a previous - // unnamed struct. + // non-free-standing tag declaration. QualType CurDeclType = getDeclType(*D); if (!Decls.empty() && !CurDeclType.isNull()) { QualType BaseType = GetBaseType(CurDeclType); - if (!BaseType.isNull() && isa<ElaboratedType>(BaseType)) - BaseType = cast<ElaboratedType>(BaseType)->getNamedType(); - if (!BaseType.isNull() && isa<TagType>(BaseType) && - cast<TagType>(BaseType)->getDecl() == Decls[0]) { + if (!BaseType.isNull() && isa<ElaboratedType>(BaseType) && + cast<ElaboratedType>(BaseType)->getOwnedTagDecl() == Decls[0]) { Decls.push_back(*D); continue; } @@ -399,9 +401,9 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { if (!Decls.empty()) ProcessDeclGroup(Decls); - // If the current declaration is an unnamed tag type, save it + // If the current declaration is not a free standing declaration, save it // so we can merge it with the subsequent declaration(s) using it. - if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) { + if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->isFreeStanding()) { Decls.push_back(*D); continue; } |