Improve AST dumping:

1) When dumping a declaration that declares a name for a type, also dump the named type.
 2) Add a #pragma clang __debug dump X, that dumps the lookup results for X in
    the current context.

llvm-svn: 257529
This commit is contained in:
Richard Smith 2016-01-12 21:59:26 +00:00
parent c81c8c66d5
commit ba3a4f917f
12 changed files with 89 additions and 4 deletions

View File

@ -490,6 +490,8 @@ def warn_pragma_diagnostic_unknown_warning :
// - #pragma __debug // - #pragma __debug
def warn_pragma_debug_unexpected_command : Warning< def warn_pragma_debug_unexpected_command : Warning<
"unexpected debug command '%0'">, InGroup<IgnoredPragmas>; "unexpected debug command '%0'">, InGroup<IgnoredPragmas>;
def warn_pragma_debug_missing_argument : Warning<
"missing argument to debug command '%0'">, InGroup<IgnoredPragmas>;
def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">; def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">;
def err_paste_at_start : Error< def err_paste_at_start : Error<

View File

@ -699,6 +699,11 @@ ANNOTATION(pragma_parser_crash)
// handles them. // handles them.
ANNOTATION(pragma_captured) ANNOTATION(pragma_captured)
// Annotation for #pragma clang __debug dump...
// The lexer produces these so that the parser and semantic analysis can
// look up and dump the operand.
ANNOTATION(pragma_dump)
// Annotation for #pragma ms_struct... // Annotation for #pragma ms_struct...
// The lexer produces these so that they only take effect when the parser // The lexer produces these so that they only take effect when the parser
// handles them. // handles them.

View File

@ -501,6 +501,10 @@ private:
/// #pragma align... /// #pragma align...
void HandlePragmaAlign(); void HandlePragmaAlign();
/// \brief Handle the annotation token produced for
/// #pragma clang __debug dump...
void HandlePragmaDump();
/// \brief Handle the annotation token produced for /// \brief Handle the annotation token produced for
/// #pragma weak id... /// #pragma weak id...
void HandlePragmaWeak(); void HandlePragmaWeak();

View File

@ -515,6 +515,7 @@ public:
configure(); configure();
} }
void dump();
void print(raw_ostream &); void print(raw_ostream &);
/// Suppress the diagnostics that would normally fire because of this /// Suppress the diagnostics that would normally fire because of this

View File

@ -7629,6 +7629,9 @@ public:
void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation, void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
StringLiteral *SegmentName); StringLiteral *SegmentName);
/// \brief Called on #pragma clang __debug dump II
void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
/// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value); void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value);

View File

@ -1055,6 +1055,7 @@ void ASTDumper::VisitTypedefDecl(const TypedefDecl *D) {
dumpType(D->getUnderlyingType()); dumpType(D->getUnderlyingType());
if (D->isModulePrivate()) if (D->isModulePrivate())
OS << " __module_private__"; OS << " __module_private__";
dumpTypeAsChild(D->getUnderlyingType());
} }
void ASTDumper::VisitEnumDecl(const EnumDecl *D) { void ASTDumper::VisitEnumDecl(const EnumDecl *D) {
@ -1226,6 +1227,7 @@ void ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) { void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) {
dumpName(D); dumpName(D);
dumpType(D->getUnderlyingType()); dumpType(D->getUnderlyingType());
dumpTypeAsChild(D->getUnderlyingType());
} }
void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
@ -1419,6 +1421,8 @@ void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D)
void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) { void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) {
OS << ' '; OS << ' ';
dumpBareDeclRef(D->getTargetDecl()); dumpBareDeclRef(D->getTargetDecl());
if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl()))
dumpTypeAsChild(TD->getTypeForDecl());
} }
void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) { void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) {

View File

@ -876,6 +876,22 @@ struct PragmaDebugHandler : public PragmaHandler {
Crasher.setKind(tok::annot_pragma_parser_crash); Crasher.setKind(tok::annot_pragma_parser_crash);
Crasher.setAnnotationRange(SourceRange(Tok.getLocation())); Crasher.setAnnotationRange(SourceRange(Tok.getLocation()));
PP.EnterToken(Crasher); PP.EnterToken(Crasher);
} else if (II->isStr("dump")) {
Token Identifier;
PP.LexUnexpandedToken(Identifier);
if (auto *DumpII = Identifier.getIdentifierInfo()) {
Token DumpAnnot;
DumpAnnot.startToken();
DumpAnnot.setKind(tok::annot_pragma_dump);
DumpAnnot.setAnnotationRange(
SourceRange(Tok.getLocation(), Identifier.getLocation()));
DumpAnnot.setAnnotationValue(DumpII);
PP.DiscardUntilEndOfDirective();
PP.EnterToken(DumpAnnot);
} else {
PP.Diag(Identifier, diag::warn_pragma_debug_missing_argument)
<< II->getName();
}
} else if (II->isStr("llvm_fatal_error")) { } else if (II->isStr("llvm_fatal_error")) {
llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error"); llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error");
} else if (II->isStr("llvm_unreachable")) { } else if (II->isStr("llvm_unreachable")) {
@ -887,7 +903,8 @@ struct PragmaDebugHandler : public PragmaHandler {
if (MacroII) if (MacroII)
PP.dumpMacroInfo(MacroII); PP.dumpMacroInfo(MacroII);
else else
PP.Diag(MacroName, diag::warn_pragma_diagnostic_invalid); PP.Diag(MacroName, diag::warn_pragma_debug_missing_argument)
<< II->getName();
} else if (II->isStr("overflow_stack")) { } else if (II->isStr("overflow_stack")) {
DebugOverflowStack(); DebugOverflowStack();
} else if (II->isStr("handle_crash")) { } else if (II->isStr("handle_crash")) {

View File

@ -377,6 +377,14 @@ void Parser::HandlePragmaAlign() {
Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc); Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
} }
void Parser::HandlePragmaDump() {
assert(Tok.is(tok::annot_pragma_dump));
IdentifierInfo *II =
reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
ConsumeToken();
}
void Parser::HandlePragmaWeak() { void Parser::HandlePragmaWeak() {
assert(Tok.is(tok::annot_pragma_weak)); assert(Tok.is(tok::annot_pragma_weak));
SourceLocation PragmaLoc = ConsumeToken(); SourceLocation PragmaLoc = ConsumeToken();

View File

@ -366,6 +366,10 @@ Retry:
case tok::annot_pragma_loop_hint: case tok::annot_pragma_loop_hint:
ProhibitAttributes(Attrs); ProhibitAttributes(Attrs);
return ParsePragmaLoopHint(Stmts, OnlyStatement, TrailingElseLoc, Attrs); return ParsePragmaLoopHint(Stmts, OnlyStatement, TrailingElseLoc, Attrs);
case tok::annot_pragma_dump:
HandlePragmaDump();
return StmtEmpty();
} }
// If we reached this code, the statement must end in a semicolon. // If we reached this code, the statement must end in a semicolon.
@ -893,6 +897,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() {
case tok::annot_pragma_ms_vtordisp: case tok::annot_pragma_ms_vtordisp:
HandlePragmaMSVtorDisp(); HandlePragmaMSVtorDisp();
break; break;
case tok::annot_pragma_dump:
HandlePragmaDump();
break;
default: default:
checkForPragmas = false; checkForPragmas = false;
break; break;

View File

@ -668,6 +668,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
case tok::annot_pragma_ms_pragma: case tok::annot_pragma_ms_pragma:
HandlePragmaMSPragma(); HandlePragmaMSPragma();
return DeclGroupPtrTy(); return DeclGroupPtrTy();
case tok::annot_pragma_dump:
HandlePragmaDump();
return DeclGroupPtrTy();
case tok::semi: case tok::semi:
// Either a C++11 empty-declaration or attribute-declaration. // Either a C++11 empty-declaration or attribute-declaration.
SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(), SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(),

View File

@ -650,6 +650,13 @@ void LookupResult::print(raw_ostream &Out) {
} }
} }
LLVM_DUMP_METHOD void LookupResult::dump() {
llvm::errs() << "lookup results for " << getLookupName().getAsString()
<< ":\n";
for (NamedDecl *D : *this)
D->dump();
}
/// \brief Lookup a builtin function, when name lookup would otherwise /// \brief Lookup a builtin function, when name lookup would otherwise
/// fail. /// fail.
static bool LookupBuiltin(Sema &S, LookupResult &R) { static bool LookupBuiltin(Sema &S, LookupResult &R) {
@ -4991,3 +4998,12 @@ const Sema::TypoExprState &Sema::getTypoExprState(TypoExpr *TE) const {
void Sema::clearDelayedTypo(TypoExpr *TE) { void Sema::clearDelayedTypo(TypoExpr *TE) {
DelayedTypos.erase(TE); DelayedTypos.erase(TE);
} }
void Sema::ActOnPragmaDump(Scope *S, SourceLocation IILoc, IdentifierInfo *II) {
DeclarationNameInfo Name(II, IILoc);
LookupResult R(*this, Name, LookupAnyName, Sema::NotForRedeclaration);
R.suppressDiagnostics();
R.setHideTags(false);
LookupName(R, S);
R.dump();
}

View File

@ -1,16 +1,31 @@
// RUN: %clang_cc1 -std=c++11 -ast-dump -ast-dump-filter Test %s | FileCheck -check-prefix DECLS %s // RUN: %clang_cc1 -std=c++11 -ast-dump -ast-dump-filter Test %s | FileCheck -check-prefix DECLS %s
// RUN: %clang_cc1 -std=c++11 -ast-dump-lookups -ast-dump-filter Test %s | FileCheck -check-prefix LOOKUPS %s // RUN: %clang_cc1 -std=c++11 -ast-dump-lookups -ast-dump-filter Test %s | FileCheck -check-prefix LOOKUPS %s
// RUN: %clang_cc1 -std=c++11 -ast-dump -ast-dump-lookups -ast-dump-filter Test %s | FileCheck -check-prefix DECLS-LOOKUPS %s // RUN: %clang_cc1 -std=c++11 -ast-dump -ast-dump-lookups -ast-dump-filter Test %s | FileCheck -check-prefix DECLS-LOOKUPS %s
// RUN: %clang_cc1 -std=c++11 -DPRAGMA -fsyntax-only %s 2>&1 | FileCheck -check-prefix PRAGMA %s
namespace Test { namespace Test {
typedef int T;
extern int a; extern int a;
int a = 0; int a = 0;
} }
#ifdef PRAGMA
#pragma clang __debug dump Test
// PRAGMA: lookup results for Test:
// PRAGMA-NEXT: NamespaceDecl {{.*}} Test
// PRAGMA-NEXT: |-TypedefDecl {{.*}} T 'int'
// PRAGMA-NEXT: | `-BuiltinType {{.*}} 'int'
// PRAGMA-NEXT: |-VarDecl [[EXTERN_A:0x[^ ]*]] {{.*}} a 'int' extern
// PRAGMA-NEXT: `-VarDecl {{.*}} prev [[EXTERN_A]] {{.*}} a 'int' cinit
// PRAGMA-NEXT: `-IntegerLiteral {{.*}} 'int' 0
#endif
namespace Test { } namespace Test { }
// DECLS: Dumping Test: // DECLS: Dumping Test:
// DECLS-NEXT: NamespaceDecl {{.*}} Test // DECLS-NEXT: NamespaceDecl {{.*}} Test
// DECLS-NEXT: |-TypedefDecl {{.*}} T 'int'
// DECLS-NEXT: | `-BuiltinType {{.*}} 'int'
// DECLS-NEXT: |-VarDecl [[EXTERN_A:0x[^ ]*]] {{.*}} a 'int' extern // DECLS-NEXT: |-VarDecl [[EXTERN_A:0x[^ ]*]] {{.*}} a 'int' extern
// DECLS-NEXT: `-VarDecl {{.*}} prev [[EXTERN_A]] {{.*}} a 'int' cinit // DECLS-NEXT: `-VarDecl {{.*}} prev [[EXTERN_A]] {{.*}} a 'int' cinit
// DECLS-NEXT: `-IntegerLiteral {{.*}} 'int' 0 // DECLS-NEXT: `-IntegerLiteral {{.*}} 'int' 0
@ -20,7 +35,7 @@ namespace Test { }
// LOOKUPS: Dumping Test: // LOOKUPS: Dumping Test:
// LOOKUPS-NEXT: StoredDeclsMap Namespace {{.*}} 'Test' // LOOKUPS-NEXT: StoredDeclsMap Namespace {{.*}} 'Test'
// LOOKUPS-NEXT: `-DeclarationName 'a' // LOOKUPS: DeclarationName 'a'
// LOOKUPS-NEXT: `-Var {{.*}} 'a' 'int' // LOOKUPS-NEXT: `-Var {{.*}} 'a' 'int'
// //
// LOOKUPS: Dumping Test: // LOOKUPS: Dumping Test:
@ -28,7 +43,7 @@ namespace Test { }
// DECLS-LOOKUPS: Dumping Test: // DECLS-LOOKUPS: Dumping Test:
// DECLS-LOOKUPS-NEXT: StoredDeclsMap Namespace {{.*}} 'Test' // DECLS-LOOKUPS-NEXT: StoredDeclsMap Namespace {{.*}} 'Test'
// DECLS-LOOKUPS-NEXT: `-DeclarationName 'a' // DECLS-LOOKUPS: -DeclarationName 'a'
// DECLS-LOOKUPS-NEXT: `-Var [[A:[^ ]*]] 'a' 'int' // DECLS-LOOKUPS-NEXT: `-Var [[A:[^ ]*]] 'a' 'int'
// DECLS-LOOKUPS-NEXT: |-VarDecl [[EXTERN_A:0x[^ ]*]] {{.*}} a 'int' extern // DECLS-LOOKUPS-NEXT: |-VarDecl [[EXTERN_A:0x[^ ]*]] {{.*}} a 'int' extern
// DECLS-LOOKUPS-NEXT: `-VarDecl [[A]] prev [[EXTERN_A]] {{.*}} a 'int' cinit // DECLS-LOOKUPS-NEXT: `-VarDecl [[A]] prev [[EXTERN_A]] {{.*}} a 'int' cinit