forked from OSchip/llvm-project
				
			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:
		
							parent
							
								
									c81c8c66d5
								
							
						
					
					
						commit
						ba3a4f917f
					
				| 
						 | 
				
			
			@ -490,6 +490,8 @@ def warn_pragma_diagnostic_unknown_warning :
 | 
			
		|||
// - #pragma __debug
 | 
			
		||||
def warn_pragma_debug_unexpected_command : Warning<
 | 
			
		||||
  "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_paste_at_start : Error<
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -699,6 +699,11 @@ ANNOTATION(pragma_parser_crash)
 | 
			
		|||
// handles them.
 | 
			
		||||
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...
 | 
			
		||||
// The lexer produces these so that they only take effect when the parser
 | 
			
		||||
// handles them.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -501,6 +501,10 @@ private:
 | 
			
		|||
  /// #pragma align...
 | 
			
		||||
  void HandlePragmaAlign();
 | 
			
		||||
 | 
			
		||||
  /// \brief Handle the annotation token produced for
 | 
			
		||||
  /// #pragma clang __debug dump...
 | 
			
		||||
  void HandlePragmaDump();
 | 
			
		||||
 | 
			
		||||
  /// \brief Handle the annotation token produced for
 | 
			
		||||
  /// #pragma weak id...
 | 
			
		||||
  void HandlePragmaWeak();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -515,6 +515,7 @@ public:
 | 
			
		|||
    configure();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void dump();
 | 
			
		||||
  void print(raw_ostream &);
 | 
			
		||||
 | 
			
		||||
  /// Suppress the diagnostics that would normally fire because of this
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7629,6 +7629,9 @@ public:
 | 
			
		|||
  void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
 | 
			
		||||
                            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
 | 
			
		||||
  void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1055,6 +1055,7 @@ void ASTDumper::VisitTypedefDecl(const TypedefDecl *D) {
 | 
			
		|||
  dumpType(D->getUnderlyingType());
 | 
			
		||||
  if (D->isModulePrivate())
 | 
			
		||||
    OS << " __module_private__";
 | 
			
		||||
  dumpTypeAsChild(D->getUnderlyingType());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ASTDumper::VisitEnumDecl(const EnumDecl *D) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1226,6 +1227,7 @@ void ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
 | 
			
		|||
void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) {
 | 
			
		||||
  dumpName(D);
 | 
			
		||||
  dumpType(D->getUnderlyingType());
 | 
			
		||||
  dumpTypeAsChild(D->getUnderlyingType());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1419,6 +1421,8 @@ void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D)
 | 
			
		|||
void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) {
 | 
			
		||||
  OS << ' ';
 | 
			
		||||
  dumpBareDeclRef(D->getTargetDecl());
 | 
			
		||||
  if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl()))
 | 
			
		||||
    dumpTypeAsChild(TD->getTypeForDecl());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -876,6 +876,22 @@ struct PragmaDebugHandler : public PragmaHandler {
 | 
			
		|||
      Crasher.setKind(tok::annot_pragma_parser_crash);
 | 
			
		||||
      Crasher.setAnnotationRange(SourceRange(Tok.getLocation()));
 | 
			
		||||
      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")) {
 | 
			
		||||
      llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error");
 | 
			
		||||
    } else if (II->isStr("llvm_unreachable")) {
 | 
			
		||||
| 
						 | 
				
			
			@ -887,7 +903,8 @@ struct PragmaDebugHandler : public PragmaHandler {
 | 
			
		|||
      if (MacroII)
 | 
			
		||||
        PP.dumpMacroInfo(MacroII);
 | 
			
		||||
      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")) {
 | 
			
		||||
      DebugOverflowStack();
 | 
			
		||||
    } else if (II->isStr("handle_crash")) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -377,6 +377,14 @@ void Parser::HandlePragmaAlign() {
 | 
			
		|||
  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() {
 | 
			
		||||
  assert(Tok.is(tok::annot_pragma_weak));
 | 
			
		||||
  SourceLocation PragmaLoc = ConsumeToken();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -366,6 +366,10 @@ Retry:
 | 
			
		|||
  case tok::annot_pragma_loop_hint:
 | 
			
		||||
    ProhibitAttributes(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.
 | 
			
		||||
| 
						 | 
				
			
			@ -893,6 +897,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() {
 | 
			
		|||
    case tok::annot_pragma_ms_vtordisp:
 | 
			
		||||
      HandlePragmaMSVtorDisp();
 | 
			
		||||
      break;
 | 
			
		||||
    case tok::annot_pragma_dump:
 | 
			
		||||
      HandlePragmaDump();
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      checkForPragmas = false;
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -668,6 +668,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
 | 
			
		|||
  case tok::annot_pragma_ms_pragma:
 | 
			
		||||
    HandlePragmaMSPragma();
 | 
			
		||||
    return DeclGroupPtrTy();
 | 
			
		||||
  case tok::annot_pragma_dump:
 | 
			
		||||
    HandlePragmaDump();
 | 
			
		||||
    return DeclGroupPtrTy();
 | 
			
		||||
  case tok::semi:
 | 
			
		||||
    // Either a C++11 empty-declaration or attribute-declaration.
 | 
			
		||||
    SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
/// fail.
 | 
			
		||||
static bool LookupBuiltin(Sema &S, LookupResult &R) {
 | 
			
		||||
| 
						 | 
				
			
			@ -4991,3 +4998,12 @@ const Sema::TypoExprState &Sema::getTypoExprState(TypoExpr *TE) const {
 | 
			
		|||
void Sema::clearDelayedTypo(TypoExpr *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();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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-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 -DPRAGMA -fsyntax-only %s 2>&1 | FileCheck -check-prefix PRAGMA %s
 | 
			
		||||
 | 
			
		||||
namespace Test {
 | 
			
		||||
  typedef int T;
 | 
			
		||||
  extern int a;
 | 
			
		||||
  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 { }
 | 
			
		||||
 | 
			
		||||
// DECLS: Dumping 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 {{.*}} prev [[EXTERN_A]] {{.*}} a 'int' cinit
 | 
			
		||||
// DECLS-NEXT:   `-IntegerLiteral {{.*}} 'int' 0
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +35,7 @@ namespace Test { }
 | 
			
		|||
 | 
			
		||||
// LOOKUPS: Dumping Test:
 | 
			
		||||
// LOOKUPS-NEXT: StoredDeclsMap Namespace {{.*}} 'Test'
 | 
			
		||||
// LOOKUPS-NEXT: `-DeclarationName 'a'
 | 
			
		||||
// LOOKUPS:      DeclarationName 'a'
 | 
			
		||||
// LOOKUPS-NEXT: `-Var {{.*}} 'a' 'int'
 | 
			
		||||
//
 | 
			
		||||
// LOOKUPS: Dumping Test:
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +43,7 @@ namespace Test { }
 | 
			
		|||
 | 
			
		||||
// DECLS-LOOKUPS: Dumping 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:     |-VarDecl [[EXTERN_A:0x[^ ]*]] {{.*}} a 'int' extern
 | 
			
		||||
// DECLS-LOOKUPS-NEXT:     `-VarDecl [[A]] prev [[EXTERN_A]] {{.*}} a 'int' cinit
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue