HelpText<"Build ASTs and then debug dump them">;
def ast_dump_all : Flag<["-"], "ast-dump-all">,
HelpText<"Build ASTs and then debug dump them, forcing deserialization">;
+def templight_dump : Flag<["-"], "templight-dump">,
+ HelpText<"Dump templight information to stdout">;
def ast_dump_lookups : Flag<["-"], "ast-dump-lookups">,
HelpText<"Build ASTs and then debug dump their name lookup tables">;
def ast_view : Flag<["-"], "ast-view">,
bool hasCodeCompletionSupport() const override { return false; }
};
+class TemplightDumpAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+ void ExecuteAction() override;
+};
+
/**
* \brief Frontend action adaptor that merges ASTs together.
*
RewriteObjC, ///< ObjC->C Rewriter.
RewriteTest, ///< Rewriter playground
RunAnalysis, ///< Run one or more source code analyses.
+ TemplightDump, ///< Dump template instantiations
MigrateSource, ///< Run migrator.
RunPreprocessorOnly ///< Just lex, no output.
};
#ifndef LLVM_CLANG_FRONTENDTOOL_UTILS_H
#define LLVM_CLANG_FRONTENDTOOL_UTILS_H
+#include <memory>
+
namespace clang {
class CompilerInstance;
+class FrontendAction;
+
+/// Construct the FrontendAction of a compiler invocation based on the
+/// options specified for the compiler invocation.
+///
+/// \return - The created FrontendAction object
+std::unique_ptr<FrontendAction> CreateFrontendAction(CompilerInstance &CI);
/// ExecuteCompilerInvocation - Execute the given actions described by the
/// compiler invocation object in the given compiler instance.
class TemplateArgumentList;
class TemplateArgumentLoc;
class TemplateDecl;
+ class TemplateInstantiationCallback;
class TemplateParameterList;
class TemplatePartialOrderingContext;
class TemplateTemplateParmDecl;
/// We are defining a synthesized function (such as a defaulted special
/// member).
DefiningSynthesizedFunction,
+
+ /// Added for Template instantiation observation.
+ /// Memoization means we are _not_ instantiating a template because
+ /// it is already instantiated (but we entered a context where we
+ /// would have had to if it was not already instantiated).
+ Memoization
} Kind;
/// \brief Was the enclosing context a non-instantiation SFINAE context?
// FIXME: Does this belong in Sema? It's tough to implement it anywhere else.
unsigned LastEmittedCodeSynthesisContextDepth = 0;
+ /// \brief The template instantiation callbacks to trace or track
+ /// instantiations (objects can be chained).
+ ///
+ /// This callbacks is used to print, trace or track template
+ /// instantiations as they are being constructed.
+ std::vector<std::unique_ptr<TemplateInstantiationCallback>>
+ TemplateInstCallbacks;
+
/// \brief The current index into pack expansion arguments that will be
/// used for substitution of parameter packs.
///
--- /dev/null
+//===- TemplateInstCallback.h - Template Instantiation Callback - C++ --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// This file defines the TemplateInstantiationCallback class, which is the
+// base class for callbacks that will be notified at template instantiations.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TEMPLATE_INST_CALLBACK_H
+#define LLVM_CLANG_TEMPLATE_INST_CALLBACK_H
+
+#include "clang/Sema/Sema.h"
+
+namespace clang {
+
+/// \brief This is a base class for callbacks that will be notified at every
+/// template instantiation.
+class TemplateInstantiationCallback {
+public:
+ virtual ~TemplateInstantiationCallback() = default;
+
+ /// \brief Called before doing AST-parsing.
+ virtual void initialize(const Sema &TheSema) = 0;
+
+ /// \brief Called after AST-parsing is completed.
+ virtual void finalize(const Sema &TheSema) = 0;
+
+ /// \brief Called when instantiation of a template just began.
+ virtual void atTemplateBegin(const Sema &TheSema,
+ const Sema::CodeSynthesisContext &Inst) = 0;
+
+ /// \brief Called when instantiation of a template is just about to end.
+ virtual void atTemplateEnd(const Sema &TheSema,
+ const Sema::CodeSynthesisContext &Inst) = 0;
+};
+
+template <class TemplateInstantiationCallbackPtrs>
+void initialize(TemplateInstantiationCallbackPtrs &Callbacks,
+ const Sema &TheSema) {
+ for (auto &C : Callbacks) {
+ if (C)
+ C->initialize(TheSema);
+ }
+}
+
+template <class TemplateInstantiationCallbackPtrs>
+void finalize(TemplateInstantiationCallbackPtrs &Callbacks,
+ const Sema &TheSema) {
+ for (auto &C : Callbacks) {
+ if (C)
+ C->finalize(TheSema);
+ }
+}
+
+template <class TemplateInstantiationCallbackPtrs>
+void atTemplateBegin(TemplateInstantiationCallbackPtrs &Callbacks,
+ const Sema &TheSema,
+ const Sema::CodeSynthesisContext &Inst) {
+ for (auto &C : Callbacks) {
+ if (C)
+ C->atTemplateBegin(TheSema, Inst);
+ }
+}
+
+template <class TemplateInstantiationCallbackPtrs>
+void atTemplateEnd(TemplateInstantiationCallbackPtrs &Callbacks,
+ const Sema &TheSema,
+ const Sema::CodeSynthesisContext &Inst) {
+ for (auto &C : Callbacks) {
+ if (C)
+ C->atTemplateEnd(TheSema, Inst);
+ }
+}
+
+} // namespace clang
+
+#endif
Opts.ProgramAction = frontend::PrintPreamble; break;
case OPT_E:
Opts.ProgramAction = frontend::PrintPreprocessedInput; break;
+ case OPT_templight_dump:
+ Opts.ProgramAction = frontend::TemplightDump; break;
case OPT_rewrite_macros:
Opts.ProgramAction = frontend::RewriteMacros; break;
case OPT_rewrite_objc:
case frontend::RewriteObjC:
case frontend::RewriteTest:
case frontend::RunAnalysis:
+ case frontend::TemplightDump:
case frontend::MigrateSource:
return false;
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Sema/TemplateInstCallback.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTWriter.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/YAMLTraits.h"
#include <memory>
#include <system_error>
using namespace clang;
+namespace {
+CodeCompleteConsumer *GetCodeCompletionConsumer(CompilerInstance &CI) {
+ return CI.hasCodeCompletionConsumer() ? &CI.getCodeCompletionConsumer()
+ : nullptr;
+}
+
+void EnsureSemaIsCreated(CompilerInstance &CI, FrontendAction &Action) {
+ if (Action.hasCodeCompletionSupport() &&
+ !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
+ CI.createCodeCompletionConsumer();
+
+ if (!CI.hasSema())
+ CI.createSema(Action.getTranslationUnitKind(),
+ GetCodeCompletionConsumer(CI));
+}
+} // namespace
+
//===----------------------------------------------------------------------===//
// Custom Actions
//===----------------------------------------------------------------------===//
ASTReader::ARR_ConfigurationMismatch);
}
+namespace {
+struct TemplightEntry {
+ std::string Name;
+ std::string Kind;
+ std::string Event;
+ std::string DefinitionLocation;
+ std::string PointOfInstantiation;
+};
+} // namespace
+
+namespace llvm {
+namespace yaml {
+template <> struct MappingTraits<TemplightEntry> {
+ static void mapping(IO &io, TemplightEntry &fields) {
+ io.mapRequired("name", fields.Name);
+ io.mapRequired("kind", fields.Kind);
+ io.mapRequired("event", fields.Event);
+ io.mapRequired("orig", fields.DefinitionLocation);
+ io.mapRequired("poi", fields.PointOfInstantiation);
+ }
+};
+} // namespace yaml
+} // namespace llvm
+
+namespace {
+class DefaultTemplateInstCallback : public TemplateInstantiationCallback {
+ using CodeSynthesisContext = Sema::CodeSynthesisContext;
+
+public:
+ virtual void initialize(const Sema &) {}
+
+ virtual void finalize(const Sema &) {}
+
+ virtual void atTemplateBegin(const Sema &TheSema,
+ const CodeSynthesisContext &Inst) override {
+ displayTemplightEntry<true>(llvm::outs(), TheSema, Inst);
+ }
+
+ virtual void atTemplateEnd(const Sema &TheSema,
+ const CodeSynthesisContext &Inst) override {
+ displayTemplightEntry<false>(llvm::outs(), TheSema, Inst);
+ }
+
+private:
+ static std::string toString(CodeSynthesisContext::SynthesisKind Kind) {
+ switch (Kind) {
+ case CodeSynthesisContext::TemplateInstantiation:
+ return "TemplateInstantiation";
+ case CodeSynthesisContext::DefaultTemplateArgumentInstantiation:
+ return "DefaultTemplateArgumentInstantiation";
+ case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
+ return "DefaultFunctionArgumentInstantiation";
+ case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution:
+ return "ExplicitTemplateArgumentSubstitution";
+ case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:
+ return "DeducedTemplateArgumentSubstitution";
+ case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
+ return "PriorTemplateArgumentSubstitution";
+ case CodeSynthesisContext::DefaultTemplateArgumentChecking:
+ return "DefaultTemplateArgumentChecking";
+ case CodeSynthesisContext::ExceptionSpecInstantiation:
+ return "ExceptionSpecInstantiation";
+ case CodeSynthesisContext::DeclaringSpecialMember:
+ return "DeclaringSpecialMember";
+ case CodeSynthesisContext::DefiningSynthesizedFunction:
+ return "DefiningSynthesizedFunction";
+ case CodeSynthesisContext::Memoization:
+ return "Memoization";
+ }
+ return "";
+ }
+
+ template <bool BeginInstantiation>
+ static void displayTemplightEntry(llvm::raw_ostream &Out, const Sema &TheSema,
+ const CodeSynthesisContext &Inst) {
+ std::string YAML;
+ {
+ llvm::raw_string_ostream OS(YAML);
+ llvm::yaml::Output YO(OS);
+ TemplightEntry Entry =
+ getTemplightEntry<BeginInstantiation>(TheSema, Inst);
+ llvm::yaml::EmptyContext Context;
+ llvm::yaml::yamlize(YO, Entry, true, Context);
+ }
+ Out << "---" << YAML << "\n";
+ }
+
+ template <bool BeginInstantiation>
+ static TemplightEntry getTemplightEntry(const Sema &TheSema,
+ const CodeSynthesisContext &Inst) {
+ TemplightEntry Entry;
+ Entry.Kind = toString(Inst.Kind);
+ Entry.Event = BeginInstantiation ? "Begin" : "End";
+ if (auto *NamedTemplate = dyn_cast_or_null<NamedDecl>(Inst.Entity)) {
+ llvm::raw_string_ostream OS(Entry.Name);
+ NamedTemplate->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);
+ const PresumedLoc DefLoc =
+ TheSema.getSourceManager().getPresumedLoc(Inst.Entity->getLocation());
+ if(!DefLoc.isInvalid())
+ Entry.DefinitionLocation = std::string(DefLoc.getFilename()) + ":" +
+ std::to_string(DefLoc.getLine()) + ":" +
+ std::to_string(DefLoc.getColumn());
+ }
+ const PresumedLoc PoiLoc =
+ TheSema.getSourceManager().getPresumedLoc(Inst.PointOfInstantiation);
+ if (!PoiLoc.isInvalid()) {
+ Entry.PointOfInstantiation = std::string(PoiLoc.getFilename()) + ":" +
+ std::to_string(PoiLoc.getLine()) + ":" +
+ std::to_string(PoiLoc.getColumn());
+ }
+ return Entry;
+ }
+};
+} // namespace
+
+std::unique_ptr<ASTConsumer>
+TemplightDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
+ return llvm::make_unique<ASTConsumer>();
+}
+
+void TemplightDumpAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+
+ // This part is normally done by ASTFrontEndAction, but needs to happen
+ // before Templight observers can be created
+ // FIXME: Move the truncation aspect of this into Sema, we delayed this till
+ // here so the source manager would be initialized.
+ EnsureSemaIsCreated(CI, *this);
+
+ CI.getSema().TemplateInstCallbacks.push_back(
+ llvm::make_unique<DefaultTemplateInstCallback>());
+ ASTFrontendAction::ExecuteAction();
+}
+
namespace {
/// \brief AST reader listener that dumps module information for a module
/// file.
using namespace clang;
using namespace llvm::opt;
+namespace clang {
+
static std::unique_ptr<FrontendAction>
CreateFrontendBaseAction(CompilerInstance &CI) {
using namespace clang::frontend;
case ParseSyntaxOnly: return llvm::make_unique<SyntaxOnlyAction>();
case ModuleFileInfo: return llvm::make_unique<DumpModuleInfoAction>();
case VerifyPCH: return llvm::make_unique<VerifyPCHAction>();
+ case TemplightDump: return llvm::make_unique<TemplightDumpAction>();
case PluginAction: {
for (FrontendPluginRegistry::iterator it =
#endif
}
-static std::unique_ptr<FrontendAction>
+std::unique_ptr<FrontendAction>
CreateFrontendAction(CompilerInstance &CI) {
// Create the underlying action.
std::unique_ptr<FrontendAction> Act = CreateFrontendBaseAction(CI);
return Act;
}
-bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) {
+bool ExecuteCompilerInvocation(CompilerInstance *Clang) {
// Honor -help.
if (Clang->getFrontendOpts().ShowHelp) {
std::unique_ptr<OptTable> Opts = driver::createDriverOptTable();
BuryPointer(std::move(Act));
return Success;
}
+
+} //namespace clang
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaConsumer.h"
+#include "clang/Sema/TemplateInstCallback.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include <cstdio>
#include <memory>
bool OldCollectStats = PrintStats;
std::swap(OldCollectStats, S.CollectStats);
+ // Initialize the template instantiation observer chain.
+ // FIXME: See note on "finalize" below.
+ initialize(S.TemplateInstCallbacks, S);
+
ASTConsumer *Consumer = &S.getASTConsumer();
std::unique_ptr<Parser> ParseOP(
Consumer->HandleTranslationUnit(S.getASTContext());
+ // Finalize the template instantiation observer chain.
+ // FIXME: This (and init.) should be done in the Sema class, but because
+ // Sema does not have a reliable "Finalize" function (it has a
+ // destructor, but it is not guaranteed to be called ("-disable-free")).
+ // So, do the initialization above and do the finalization here:
+ finalize(S.TemplateInstCallbacks, S);
+
std::swap(OldCollectStats, S.CollectStats);
if (PrintStats) {
llvm::errs() << "\nSTATISTICS:\n";
#include "clang/Sema/SemaConsumer.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/TemplateDeduction.h"
+#include "clang/Sema/TemplateInstCallback.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
using namespace clang;
#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
+#include "clang/Sema/TemplateInstCallback.h"
using namespace clang;
using namespace sema;
case DeclaringSpecialMember:
case DefiningSynthesizedFunction:
return false;
+
+ // This function should never be called when Kind's value is Memoization.
+ case Memoization:
+ break;
}
llvm_unreachable("Invalid SynthesisKind!");
!SemaRef.InstantiatingSpecializations
.insert(std::make_pair(Inst.Entity->getCanonicalDecl(), Inst.Kind))
.second;
+ atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, Inst);
}
}
std::make_pair(Active.Entity, Active.Kind));
}
- SemaRef.popCodeSynthesisContext();
+ atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef,
+ SemaRef.CodeSynthesisContexts.back());
+ SemaRef.popCodeSynthesisContext();
Invalid = true;
}
}
<< cast<CXXRecordDecl>(Active->Entity) << Active->SpecialMember;
break;
- case CodeSynthesisContext::DefiningSynthesizedFunction:
+ case CodeSynthesisContext::DefiningSynthesizedFunction: {
// FIXME: For synthesized members other than special members, produce a note.
auto *MD = dyn_cast<CXXMethodDecl>(Active->Entity);
auto CSM = MD ? getSpecialMember(MD) : CXXInvalid;
}
break;
}
+
+ case CodeSynthesisContext::Memoization:
+ break;
+ }
}
}
// This happens in a context unrelated to template instantiation, so
// there is no SFINAE.
return None;
+
+ case CodeSynthesisContext::Memoization:
+ break;
}
// The inner context was transparent for SFINAE. If it occurred within a
#include "clang/Sema/Lookup.h"
#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateInstCallback.h"
using namespace clang;
assert(FunTmpl->getTemplatedDecl() == Tmpl &&
"Deduction from the wrong function template?");
(void) FunTmpl;
+ atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst);
ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
ActiveInst.Entity = New;
+ atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst);
}
}
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateInstCallback.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
diagnoseMissingImport(Loc, SuggestedDef, MissingImportKind::Definition,
/*Recover*/TreatAsComplete);
return !TreatAsComplete;
+ } else if (Def && !TemplateInstCallbacks.empty()) {
+ CodeSynthesisContext TempInst;
+ TempInst.Kind = CodeSynthesisContext::Memoization;
+ TempInst.Template = Def;
+ TempInst.Entity = Def;
+ TempInst.PointOfInstantiation = Loc;
+ atTemplateBegin(TemplateInstCallbacks, *this, TempInst);
+ atTemplateEnd(TemplateInstCallbacks, *this, TempInst);
}
return false;
--- /dev/null
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+
+template <class T>
+int foo(T){return 0;}
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+foo$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-deduced-func.cpp:4:5'}}
+// CHECK: {{^poi:[ ]+'.*templight-deduced-func.cpp:44:12'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+foo$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-deduced-func.cpp:4:5'}}
+// CHECK: {{^poi:[ ]+'.*templight-deduced-func.cpp:44:12'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-deduced-func.cpp:4:5'}}
+// CHECK: {{^poi:[ ]+'.*templight-deduced-func.cpp:44:12'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-deduced-func.cpp:4:5'}}
+// CHECK: {{^poi:[ ]+'.*templight-deduced-func.cpp:44:12'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-deduced-func.cpp:4:5'}}
+// CHECK: {{^poi:[ ]+'.*templight-deduced-func.cpp:44:12'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-deduced-func.cpp:4:5'}}
+// CHECK: {{^poi:[ ]+'.*templight-deduced-func.cpp:44:12'$}}
+int gvar = foo(0);
--- /dev/null
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+template<class T, class U = T>
+class A {};
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A::U'$}}
+// CHECK: {{^kind:[ ]+DefaultTemplateArgumentInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:2:25'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:1'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A::U'$}}
+// CHECK: {{^kind:[ ]+DefaultTemplateArgumentInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:2:25'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:1'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A::U'$}}
+// CHECK: {{^kind:[ ]+DefaultTemplateArgumentChecking$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:2:25'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:6'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A::U'$}}
+// CHECK: {{^kind:[ ]+DefaultTemplateArgumentChecking$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:2:25'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:6'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+A<int> a;
--- /dev/null
+// RUN: %clang_cc1 -std=c++14 -templight-dump %s 2>&1 | FileCheck %s
+template <class T>
+void foo(T b = 0) {};
+
+int main()
+{
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+foo$}}
+// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+foo$}}
+// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+foo$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+foo$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+b$}}
+// CHECK: {{^kind:[ ]+DefaultFunctionArgumentInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:12'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+b$}}
+// CHECK: {{^kind:[ ]+DefaultFunctionArgumentInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:12'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+ foo<int>();
+}
--- /dev/null
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+template <class T = int>
+class A {};
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A::T'$}}
+// CHECK: {{^kind:[ ]+DefaultTemplateArgumentChecking$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:2:17'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A::T'$}}
+// CHECK: {{^kind:[ ]+DefaultTemplateArgumentChecking$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:2:17'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+A<> a;
--- /dev/null
+// RUN: %clang_cc1 -templight-dump -std=c++14 %s 2>&1 | FileCheck %s
+template <bool B>
+void f() noexcept(B) {}
+
+int main()
+{
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<false>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<false>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<false>'$}}
+// CHECK: {{^kind:[ ]+ExceptionSpecInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<false>'$}}
+// CHECK: {{^kind:[ ]+ExceptionSpecInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<false>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<false>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+ f<false>();
+}
--- /dev/null
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+template <class T>
+void f(){}
+
+int main()
+{
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+ f<int>();
+}
--- /dev/null
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+
+template <class T>
+struct foo {};
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-memoization.cpp:18:10'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-memoization.cpp:18:10'$}}
+foo<int> x;
+
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-memoization.cpp:41:10'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-memoization.cpp:41:10'$}}
+foo<int> y;
+
--- /dev/null
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+
+template <int N>
+struct fib
+{
+ static const int value = fib<N-1>::value + fib<N-2>::value;
+};
+
+template <>
+struct fib<0>
+{
+ static const int value = 1;
+};
+
+template <>
+struct fib<1>
+{
+ static const int value = 1;
+};
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<4>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:173:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<4>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:173:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<4>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:173:8'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<3>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<3>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<3>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<1>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:16:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<1>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:16:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<0>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:10:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:46'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<0>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:10:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:46'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<1>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:16:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:46'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<1>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:16:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:46'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<3>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<3>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<3>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:46'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:46'$}}
+// CHECK-LABEL: {{^---$}}
+//
+// CHECK: {{^name:[ ]+'fib<4>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:173:8'$}}
+fib<4> x;
+
--- /dev/null
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+
+template <int N>
+struct foo : foo<N - 1> {};
+
+template <>
+struct foo<0> {};
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:84:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:84:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:84:8'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<1>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<1>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<1>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<0>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:7:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<0>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:7:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<1>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<1>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<1>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:84:8'$}}
+foo<2> x;
--- /dev/null
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+
+template <class T>
+struct foo {};
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-one-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-one-instantiation.cpp:18:10'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-one-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-one-instantiation.cpp:18:10'$}}
+foo<int> x;
--- /dev/null
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+template<class T>
+class A {};
+
+template <template <class Inner> class Outer>
+class B {};
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B::Outer'$}}
+// CHECK: {{^kind:[ ]+PriorTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:5:40'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:1'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B::Outer'$}}
+// CHECK: {{^kind:[ ]+PriorTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:5:40'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:1'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+B<A> b;