// - #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<
// 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.
/// #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();
configure();
}
+ void dump();
void print(raw_ostream &);
/// Suppress the diagnostics that would normally fire because of this
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);
dumpType(D->getUnderlyingType());
if (D->isModulePrivate())
OS << " __module_private__";
+ dumpTypeAsChild(D->getUnderlyingType());
}
void ASTDumper::VisitEnumDecl(const EnumDecl *D) {
void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) {
dumpName(D);
dumpType(D->getUnderlyingType());
+ dumpTypeAsChild(D->getUnderlyingType());
}
void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *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) {
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")) {
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")) {
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();
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.
case tok::annot_pragma_ms_vtordisp:
HandlePragmaMSVtorDisp();
break;
+ case tok::annot_pragma_dump:
+ HandlePragmaDump();
+ break;
default:
checkForPragmas = false;
break;
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(),
}
}
+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) {
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();
+}
// 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
// LOOKUPS: Dumping Test:
// LOOKUPS-NEXT: StoredDeclsMap Namespace {{.*}} 'Test'
-// LOOKUPS-NEXT: `-DeclarationName 'a'
-// LOOKUPS-NEXT: `-Var {{.*}} 'a' 'int'
+// LOOKUPS: DeclarationName 'a'
+// LOOKUPS-NEXT: `-Var {{.*}} 'a' 'int'
//
// LOOKUPS: Dumping Test:
// LOOKUPS-NEXT: Lookup map is in primary DeclContext
// 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