Pretty-print anonymous types using their kind and presumed location.

Fixes PR6643.  Patch by Mike M!

llvm-svn: 98946
This commit is contained in:
John McCall 2010-03-19 07:56:44 +00:00
parent a0296f7987
commit ef01f71a5a
5 changed files with 38 additions and 19 deletions

View File

@ -1889,16 +1889,16 @@ def err_stmtexpr_file_scope : Error<
"statement expression not allowed at file scope">; "statement expression not allowed at file scope">;
def warn_mixed_sign_comparison : Warning< def warn_mixed_sign_comparison : Warning<
"comparison of integers of different signs: %0 and %1">, "comparison of integers of different signs: %0 and %1">,
InGroup<DiagGroup<"sign-compare">>, DefaultIgnore; InGroup<SignCompare>, DefaultIgnore;
def warn_mixed_sign_conditional : Warning< def warn_mixed_sign_conditional : Warning<
"operands of ? are integers of different signs: %0 and %1">, "operands of ? are integers of different signs: %0 and %1">,
InGroup<DiagGroup<"sign-compare">>, DefaultIgnore; InGroup<SignCompare>, DefaultIgnore;
def warn_lunsigned_always_true_comparison : Warning< def warn_lunsigned_always_true_comparison : Warning<
"comparison of unsigned expression %0 is always %1">, "comparison of unsigned expression %0 is always %1">,
InGroup<DiagGroup<"sign-compare">>, DefaultIgnore; InGroup<SignCompare>, DefaultIgnore;
def warn_runsigned_always_true_comparison : Warning< def warn_runsigned_always_true_comparison : Warning<
"comparison of %0 unsigned expression is always %1">, "comparison of %0 unsigned expression is always %1">,
InGroup<DiagGroup<"sign-compare">>, DefaultIgnore; InGroup<SignCompare>, DefaultIgnore;
def err_invalid_this_use : Error< def err_invalid_this_use : Error<
"invalid use of 'this' outside of a nonstatic member function">; "invalid use of 'this' outside of a nonstatic member function">;

View File

@ -18,6 +18,7 @@
#include "clang/AST/Type.h" #include "clang/AST/Type.h"
#include "clang/AST/PrettyPrinter.h" #include "clang/AST/PrettyPrinter.h"
#include "clang/Basic/LangOptions.h" #include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
using namespace clang; using namespace clang;
@ -412,10 +413,12 @@ void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) {
return; return;
std::string Buffer; std::string Buffer;
bool HasKindDecoration = false;
// We don't print tags unless this is an elaborated type. // We don't print tags unless this is an elaborated type.
// In C, we just assume every RecordType is an elaborated type. // In C, we just assume every RecordType is an elaborated type.
if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) { if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) {
HasKindDecoration = true;
Buffer += D->getKindName(); Buffer += D->getKindName();
Buffer += ' '; Buffer += ' ';
} }
@ -425,15 +428,31 @@ void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) {
// this will always be empty. // this will always be empty.
AppendScope(D->getDeclContext(), Buffer); AppendScope(D->getDeclContext(), Buffer);
const char *ID;
if (const IdentifierInfo *II = D->getIdentifier()) if (const IdentifierInfo *II = D->getIdentifier())
ID = II->getNameStart(); Buffer += II->getNameStart();
else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) { else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) {
assert(Typedef->getIdentifier() && "Typedef without identifier?"); assert(Typedef->getIdentifier() && "Typedef without identifier?");
ID = Typedef->getIdentifier()->getNameStart(); Buffer += Typedef->getIdentifier()->getNameStart();
} else } else {
ID = "<anonymous>"; // Make an unambiguous representation for anonymous types, e.g.
Buffer += ID; // <anonymous enum at /usr/include/string.h:120:9>
llvm::raw_string_ostream OS(Buffer);
OS << "<anonymous";
// Suppress the redundant tag keyword if we just printed one.
// We don't have to worry about ElaboratedTypes here because you can't
// refer to an anonymous type with one.
if (!HasKindDecoration)
OS << " " << D->getKindName();
PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
D->getLocation());
OS << " at " << PLoc.getFilename()
<< ':' << PLoc.getLine()
<< ':' << PLoc.getColumn()
<< '>';
OS.flush();
}
// If this is a class template specialization, print the template // If this is a class template specialization, print the template
// arguments. // arguments.

View File

@ -46,25 +46,25 @@ union U1 {
union U2 { union U2 {
struct { struct {
Virtual v; // expected-note {{because type 'U2::<anonymous>' has a member with a non-trivial copy constructor}} Virtual v; // expected-note {{because type 'U2::<anonymous struct}}
} m1; // expected-error {{union member 'm1' has a non-trivial copy constructor}} } m1; // expected-error {{union member 'm1' has a non-trivial copy constructor}}
struct { struct {
VirtualBase vbase; // expected-note {{because type 'U2::<anonymous>' has a member with a non-trivial copy constructor}} VirtualBase vbase; // expected-note {{because type 'U2::<anonymous struct}}
} m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}} } m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}}
struct { struct {
Ctor ctor; // expected-note {{because type 'U2::<anonymous>' has a member with a non-trivial constructor}} Ctor ctor; // expected-note {{because type 'U2::<anonymous struct}}
} m3; // expected-error {{union member 'm3' has a non-trivial constructor}} } m3; // expected-error {{union member 'm3' has a non-trivial constructor}}
struct { struct {
Ctor2 ctor2; // expected-note {{because type 'U2::<anonymous>' has a member with a non-trivial constructor}} Ctor2 ctor2; // expected-note {{because type 'U2::<anonymous struct}}
} m3a; // expected-error {{union member 'm3a' has a non-trivial constructor}} } m3a; // expected-error {{union member 'm3a' has a non-trivial constructor}}
struct { struct {
CopyCtor copyctor; // expected-note {{because type 'U2::<anonymous>' has a member with a non-trivial copy constructor}} CopyCtor copyctor; // expected-note {{because type 'U2::<anonymous struct}}
} m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}} } m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}}
struct { struct {
CopyAssign copyassign; // expected-note {{because type 'U2::<anonymous>' has a member with a non-trivial copy assignment operator}} CopyAssign copyassign; // expected-note {{because type 'U2::<anonymous struct}}
} m5; // expected-error {{union member 'm5' has a non-trivial copy assignment operator}} } m5; // expected-error {{union member 'm5' has a non-trivial copy assignment operator}}
struct { struct {
Dtor dtor; // expected-note {{because type 'U2::<anonymous>' has a member with a non-trivial destructor}} Dtor dtor; // expected-note {{because type 'U2::<anonymous struct}}
} m6; // expected-error {{union member 'm6' has a non-trivial destructor}} } m6; // expected-error {{union member 'm6' has a non-trivial destructor}}
struct { struct {
Okay okay; Okay okay;

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 %s -verify -fsyntax-only // RUN: %clang_cc1 %s -verify -fsyntax-only
int a; int a;
struct {int x;} x = a; // expected-error {{incompatible type initializing 'int', expected 'struct <anonymous>'}} struct {int x;} x = a; // expected-error {{incompatible type initializing 'int', expected 'struct <anonymous}}

View File

@ -17,7 +17,7 @@ void test() {
switch (s) {} // expected-error {{statement requires expression of integer type ('struct S' invalid)}} switch (s) {} // expected-error {{statement requires expression of integer type ('struct S' invalid)}}
while (struct S {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{no viable conversion}} expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} expected-note{{candidate constructor (the implicit copy constructor)}} while (struct S {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{no viable conversion}} expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} expected-note{{candidate constructor (the implicit copy constructor)}}
while (struct {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{no viable conversion}} expected-error {{value of type 'struct <anonymous>' is not contextually convertible to 'bool'}} expected-note{{candidate constructor (the implicit copy constructor)}} while (struct {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{no viable conversion}} expected-error {{not contextually convertible to 'bool'}} expected-note{{candidate constructor (the implicit copy constructor)}}
switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize}} \ switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize}} \
// expected-warning{{enumeration value 'E' not handled in switch}} // expected-warning{{enumeration value 'E' not handled in switch}}