]> granicus.if.org Git - clang/commitdiff
[Templight] Template Instantiation Observer
authorGabor Horvath <xazax.hun@gmail.com>
Sat, 10 Feb 2018 14:04:45 +0000 (14:04 +0000)
committerGabor Horvath <xazax.hun@gmail.com>
Sat, 10 Feb 2018 14:04:45 +0000 (14:04 +0000)
This patch adds a base-class called TemplateInstantiationObserver which gets
notified whenever a template instantiation is entered or exited during
semantic analysis. This is a base class used to implement the template
profiling and debugging tool called
Templight (https://github.com/mikael-s-persson/templight).

The patch also makes a few more changes:

* ActiveTemplateInstantiation class is moved out of the Sema class (so it can be used with inclusion of Sema.h).
* CreateFrontendAction function in front-end utilities is given external linkage (not longer a hidden static function).
* TemplateInstObserverChain data member added to Sema class to hold the list of template-inst observers.
* Notifications to the template-inst observer are added at the key places where templates are instantiated.

Patch by: Abel Sinkovics!

Differential Revision: https://reviews.llvm.org/D5767

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@324808 91177308-0d34-0410-b5e6-96231b3b80d8

25 files changed:
include/clang/Driver/CC1Options.td
include/clang/Frontend/FrontendActions.h
include/clang/Frontend/FrontendOptions.h
include/clang/FrontendTool/Utils.h
include/clang/Sema/Sema.h
include/clang/Sema/TemplateInstCallback.h [new file with mode: 0644]
lib/Frontend/CompilerInvocation.cpp
lib/Frontend/FrontendActions.cpp
lib/FrontendTool/ExecuteCompilerInvocation.cpp
lib/Parse/ParseAST.cpp
lib/Sema/Sema.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Sema/SemaType.cpp
test/Templight/templight-deduced-func.cpp [new file with mode: 0644]
test/Templight/templight-default-arg-inst.cpp [new file with mode: 0644]
test/Templight/templight-default-func-arg.cpp [new file with mode: 0644]
test/Templight/templight-default-template-arg.cpp [new file with mode: 0644]
test/Templight/templight-exception-spec-func.cpp [new file with mode: 0644]
test/Templight/templight-explicit-template-arg.cpp [new file with mode: 0644]
test/Templight/templight-memoization.cpp [new file with mode: 0644]
test/Templight/templight-nested-memoization.cpp [new file with mode: 0644]
test/Templight/templight-nested-template-instantiation.cpp [new file with mode: 0644]
test/Templight/templight-one-instantiation.cpp [new file with mode: 0644]
test/Templight/templight-prior-template-arg.cpp [new file with mode: 0644]

index 7dea88b62cc196d88e2d2c096c421ea932af19c3..f8672188d2567d53232cd296fbd7430d3c73bb6a 100644 (file)
@@ -533,6 +533,8 @@ def ast_dump : Flag<["-"], "ast-dump">,
   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">,
index fa1529a3d65dcbcec5360b19c0aeb3d5b59b3c16..df0b7a6406755ed2edc8fb5c7e0a87e30be170b4 100644 (file)
@@ -167,6 +167,14 @@ public:
   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.
  *
index 5192a3774cc1ddb7fe2ac65ca3291f6030c39c7b..c60950051633370e0ea3682a83a346debc777f6f 100644 (file)
@@ -58,6 +58,7 @@ namespace frontend {
     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.
   };
index 031ee7df70aedf3d931d5a987ab2618402ff0c33..2e6b7b5076bb631d2079693adce03ea2798ad9c8 100644 (file)
 #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.
index 3759b58e72e72a57043ed146452bb7a9e9d77404..832a3d0e7a0282240f452fe7f8d586d4359897c4 100644 (file)
@@ -172,6 +172,7 @@ namespace clang {
   class TemplateArgumentList;
   class TemplateArgumentLoc;
   class TemplateDecl;
+  class TemplateInstantiationCallback;
   class TemplateParameterList;
   class TemplatePartialOrderingContext;
   class TemplateTemplateParmDecl;
@@ -7127,6 +7128,12 @@ public:
       /// 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?
@@ -7235,6 +7242,14 @@ public:
   // 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.
   ///
diff --git a/include/clang/Sema/TemplateInstCallback.h b/include/clang/Sema/TemplateInstCallback.h
new file mode 100644 (file)
index 0000000..14a3d0b
--- /dev/null
@@ -0,0 +1,83 @@
+//===- 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
index b107f65adf177457461467547785f108fbced8d6..95fd1665b406e4d6fda48e9c983de1fde51b1cf1 100644 (file)
@@ -1358,6 +1358,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
       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:
@@ -2620,6 +2622,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
   case frontend::RewriteObjC:
   case frontend::RewriteTest:
   case frontend::RunAnalysis:
+  case frontend::TemplightDump:
   case frontend::MigrateSource:
     return false;
 
index ffa5b410d2d8f3c4469a233285c62694b80fe2d5..4a7e6f339744839abc5bdb43a3311a60aefee637 100644 (file)
 #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
 //===----------------------------------------------------------------------===//
@@ -261,6 +280,140 @@ void VerifyPCHAction::ExecuteAction() {
                   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.
index 4167e1fe20b811eabc214fb78e1ee8333fd726c2..59f30d5c306b42ef822f56f01ac6d9b22b097011 100644 (file)
@@ -32,6 +32,8 @@
 using namespace clang;
 using namespace llvm::opt;
 
+namespace clang {
+
 static std::unique_ptr<FrontendAction>
 CreateFrontendBaseAction(CompilerInstance &CI) {
   using namespace clang::frontend;
@@ -63,6 +65,7 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
   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 =
@@ -122,7 +125,7 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
 #endif
 }
 
-static std::unique_ptr<FrontendAction>
+std::unique_ptr<FrontendAction>
 CreateFrontendAction(CompilerInstance &CI) {
   // Create the underlying action.
   std::unique_ptr<FrontendAction> Act = CreateFrontendBaseAction(CI);
@@ -173,7 +176,7 @@ CreateFrontendAction(CompilerInstance &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();
@@ -254,3 +257,5 @@ bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) {
     BuryPointer(std::move(Act));
   return Success;
 }
+
+} //namespace clang 
index d018d4c08ed967ef761e8370aa7e1df2bea66a3f..354b3800791407d9418f8c90730885687ae3420c 100644 (file)
@@ -21,6 +21,7 @@
 #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>
@@ -121,6 +122,10 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
   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(
@@ -158,6 +163,13 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
   
   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";
index 45fd2d3249dc597741d4e02ec98c49826eaa0958..65183b434b1ee62cfee3915823dfcf5815efa99a 100644 (file)
@@ -37,6 +37,7 @@
 #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;
index 313d99cf453d552c512e6484af018ba92b0ede72..489d026027de195020b56d1293fd5df08ff4ce9c 100644 (file)
@@ -25,6 +25,7 @@
 #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;
@@ -199,6 +200,10 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
   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!");
@@ -235,6 +240,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
         !SemaRef.InstantiatingSpecializations
              .insert(std::make_pair(Inst.Entity->getCanonicalDecl(), Inst.Kind))
              .second;
+    atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, Inst);
   }
 }
 
@@ -394,8 +400,10 @@ void Sema::InstantiatingTemplate::Clear() {
           std::make_pair(Active.Entity, Active.Kind));
     }
 
-    SemaRef.popCodeSynthesisContext();
+    atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef,
+                  SemaRef.CodeSynthesisContexts.back());
 
+    SemaRef.popCodeSynthesisContext();
     Invalid = true;
   }
 }
@@ -626,7 +634,7 @@ void Sema::PrintInstantiationStack() {
         << 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;
@@ -637,6 +645,10 @@ void Sema::PrintInstantiationStack() {
       }
       break;
     }
+
+    case CodeSynthesisContext::Memoization:
+      break;
+    }
   }
 }
 
@@ -682,6 +694,9 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
       // 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
index b8b74408cb82446cd568adcf154997210437b894..15b53ca761270a107688c50c0b204ec12c593125 100644 (file)
@@ -23,6 +23,7 @@
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/PrettyDeclStackTrace.h"
 #include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateInstCallback.h"
 
 using namespace clang;
 
@@ -3648,8 +3649,10 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
       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);
     }
   }
 
index 8219d4dbb70b2a49c91a109ee3e8b5182ec7436c..8f3b359fde18e7f973cc3d6adef8e4d29bfa6f95 100644 (file)
@@ -31,6 +31,7 @@
 #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"
@@ -7565,6 +7566,14 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
         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;
diff --git a/test/Templight/templight-deduced-func.cpp b/test/Templight/templight-deduced-func.cpp
new file mode 100644 (file)
index 0000000..779fb5f
--- /dev/null
@@ -0,0 +1,44 @@
+// 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);
diff --git a/test/Templight/templight-default-arg-inst.cpp b/test/Templight/templight-default-arg-inst.cpp
new file mode 100644 (file)
index 0000000..fe2bab3
--- /dev/null
@@ -0,0 +1,82 @@
+// 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;
diff --git a/test/Templight/templight-default-func-arg.cpp b/test/Templight/templight-default-func-arg.cpp
new file mode 100644 (file)
index 0000000..19e6039
--- /dev/null
@@ -0,0 +1,73 @@
+// 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>();
+}
diff --git a/test/Templight/templight-default-template-arg.cpp b/test/Templight/templight-default-template-arg.cpp
new file mode 100644 (file)
index 0000000..5d2ccb4
--- /dev/null
@@ -0,0 +1,69 @@
+// 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;
diff --git a/test/Templight/templight-exception-spec-func.cpp b/test/Templight/templight-exception-spec-func.cpp
new file mode 100644 (file)
index 0000000..39a66d0
--- /dev/null
@@ -0,0 +1,73 @@
+// 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>();
+}
diff --git a/test/Templight/templight-explicit-template-arg.cpp b/test/Templight/templight-explicit-template-arg.cpp
new file mode 100644 (file)
index 0000000..678cba2
--- /dev/null
@@ -0,0 +1,59 @@
+// 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>();
+}
diff --git a/test/Templight/templight-memoization.cpp b/test/Templight/templight-memoization.cpp
new file mode 100644 (file)
index 0000000..ddf2447
--- /dev/null
@@ -0,0 +1,42 @@
+// 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;
+
diff --git a/test/Templight/templight-nested-memoization.cpp b/test/Templight/templight-nested-memoization.cpp
new file mode 100644 (file)
index 0000000..37e8483
--- /dev/null
@@ -0,0 +1,174 @@
+// 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;
+
diff --git a/test/Templight/templight-nested-template-instantiation.cpp b/test/Templight/templight-nested-template-instantiation.cpp
new file mode 100644 (file)
index 0000000..a064c16
--- /dev/null
@@ -0,0 +1,84 @@
+// 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;
diff --git a/test/Templight/templight-one-instantiation.cpp b/test/Templight/templight-one-instantiation.cpp
new file mode 100644 (file)
index 0000000..e865ef3
--- /dev/null
@@ -0,0 +1,18 @@
+// 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;
diff --git a/test/Templight/templight-prior-template-arg.cpp b/test/Templight/templight-prior-template-arg.cpp
new file mode 100644 (file)
index 0000000..e9b1dd4
--- /dev/null
@@ -0,0 +1,72 @@
+// 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;