<div dir="ltr">One of the commits in this sequence seems to be breaking a couple tests: <a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/14892">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/14892</a>.<div><br></div><div><pre style="font-family:"Courier New",courier,monotype,monospace;color:rgb(0,0,0);font-size:medium;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><span class="gmail-stdout" style="font-family:"Courier New",courier,monotype,monospace;color:black">Testing: 0 .. 10.. 20.. 30.. 40.. 50.. 60.. 70..
FAIL: Clang :: TableGen/<a href="http://anonymous-groups.td">anonymous-groups.td</a> (9683 of 12091)
******************** TEST 'Clang :: TableGen/<a href="http://anonymous-groups.td">anonymous-groups.td</a>' FAILED ********************
Script:
--
clang-tblgen -gen-clang-diag-groups -I/b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/<a href="http://anonymous-groups.td">anonymous-groups.td</a> -o /dev/null 2>&1 | /b/sanitizer-x86_64-linux-fast/build/llvm_build_asan/bin/FileCheck --strict-whitespace /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/<a href="http://anonymous-groups.td">anonymous-groups.td</a>
--
Exit Code: 1
Command Output (stderr):
--
/b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/anonymous-groups.td:10:16: error: expected string not found in input
// CHECK: anonymous-groups.td:[[@LINE-1]]:41: error: group 'name' is referred to anonymously
^
<stdin>:1:1: note: scanning from here
Included from /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/<a href="http://anonymous-groups.td:2">anonymous-groups.td:2</a>:
^
<stdin>:1:1: note: with expression "@LINE-1" equal to "9"
Included from /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/<a href="http://anonymous-groups.td:2">anonymous-groups.td:2</a>:
^
<stdin>:2:71: note: possible intended match here
/b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/DiagnosticBase.inc:15:7: error: group 'name' is referred to anonymously
^
--
********************
Testing: 0 .. 10.. 20.. 30.. 40.. 50.. 60.. 70..
FAIL: Clang :: TableGen/<a href="http://tg-fixits.td">tg-fixits.td</a> (9690 of 12091)
******************** TEST 'Clang :: TableGen/<a href="http://tg-fixits.td">tg-fixits.td</a>' FAILED ********************
Script:
--
clang-tblgen -gen-clang-diag-groups -I/b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/<a href="http://tg-fixits.td">tg-fixits.td</a> -o /dev/null 2>&1 | /b/sanitizer-x86_64-linux-fast/build/llvm_build_asan/bin/FileCheck --strict-whitespace /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/<a href="http://tg-fixits.td">tg-fixits.td</a>
--
Exit Code: 1
Command Output (stderr):
--
/b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/tg-fixits.td:7:16: error: expected string not found in input
// CHECK: tg-fixits.td:[[@LINE-1]]:41: error: group 'name' is referred to anonymously
^
<stdin>:1:1: note: scanning from here
Included from /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/<a href="http://tg-fixits.td:2">tg-fixits.td:2</a>:
^
<stdin>:1:1: note: with expression "@LINE-1" equal to "6"
Included from /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/<a href="http://tg-fixits.td:2">tg-fixits.td:2</a>:
^
<stdin>:2:76: note: possible intended match here
/b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/DiagnosticBase.inc:15:7: error: group 'name' is referred to anonymously
^
--
********************
Testing: 0 .. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90..
Testing Time: 226.63s
********************
Failing Tests (2):
Clang :: TableGen/<a href="http://anonymous-groups.td">anonymous-groups.td</a>
Clang :: TableGen/<a href="http://tg-fixits.td">tg-fixits.td</a>
Expected Passes : 12019
Expected Failures : 19
Unsupported Tests : 51
Unexpected Failures: 2
FAILED: tools/clang/test/CMakeFiles/check-clang
</span></pre><br class="gmail-Apple-interchange-newline">Please take a look.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Mar 6, 2018 at 5:49 AM, Nicolai Haehnle via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: nha<br>
Date: Tue Mar 6 05:49:01 2018<br>
New Revision: 326788<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=326788&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=326788&view=rev</a><br>
Log:<br>
TableGen: Delay instantiating inline anonymous records<br>
<br>
Summary:<br>
Only instantiate anonymous records once all variable references in template<br>
arguments have been resolved. This allows patterns like the new test case,<br>
which in practice can appear in expressions like:<br>
<br>
class IntrinsicTypeProfile<list<<wbr>LLVMType> ty, int shift> {<br>
list<LLVMType> types =<br>
!listconcat(ty, [llvm_any_ty, LLVMMatchType<shift>]);<br>
}<br>
<br>
class FooIntrinsic<<wbr>IntrinsicTypeProfile P, ...><br>
: Intrinsic<..., P.types, ...>;<br>
<br>
Without this change, the anonymous LLVMMatchType instantiation would<br>
never get resolved.<br>
<br>
Another consequence of this change is that anonymous inline<br>
instantiations are uniqued via the folding set of the newly introduced<br>
VarDefInit.<br>
<br>
Change-Id: I7a7041a20e297cf98c9109b28d85e<wbr>64e176c932a<br>
<br>
Reviewers: arsenm, craig.topper, tra, MartinO<br>
<br>
Subscribers: wdng, llvm-commits<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D43756" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D43756</a><br>
<br>
Modified:<br>
llvm/trunk/include/llvm/<wbr>TableGen/Record.h<br>
llvm/trunk/lib/TableGen/<wbr>Record.cpp<br>
llvm/trunk/lib/TableGen/<wbr>TGParser.cpp<br>
llvm/trunk/test/TableGen/<wbr>AnonDefinitionOnDemand.td<br>
<br>
Modified: llvm/trunk/include/llvm/<wbr>TableGen/Record.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/TableGen/Record.h?rev=326788&r1=326787&r2=326788&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/include/<wbr>llvm/TableGen/Record.h?rev=<wbr>326788&r1=326787&r2=326788&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/<wbr>TableGen/Record.h (original)<br>
+++ llvm/trunk/include/llvm/<wbr>TableGen/Record.h Tue Mar 6 05:49:01 2018<br>
@@ -320,6 +320,7 @@ protected:<br>
IK_VarInit,<br>
IK_VarListElementInit,<br>
IK_VarBitInit,<br>
+ IK_VarDefInit,<br>
IK_LastTypedInit,<br>
IK_UnsetInit<br>
};<br>
@@ -1052,6 +1053,58 @@ public:<br>
}<br>
};<br>
<br>
+/// classname<targs...> - Represent an uninstantiated anonymous class<br>
+/// instantiation.<br>
+class VarDefInit final : public TypedInit, public FoldingSetNode,<br>
+ public TrailingObjects<VarDefInit, Init *> {<br>
+ Record *Class;<br>
+ DefInit *Def = nullptr; // after instantiation<br>
+ unsigned NumArgs;<br>
+<br>
+ explicit VarDefInit(Record *Class, unsigned N)<br>
+ : TypedInit(IK_VarDefInit, RecordRecTy::get(Class)), Class(Class), NumArgs(N) {}<br>
+<br>
+ DefInit *instantiate();<br>
+<br>
+public:<br>
+ VarDefInit(const VarDefInit &) = delete;<br>
+ VarDefInit &operator=(const VarDefInit &) = delete;<br>
+<br>
+ // Do not use sized deallocation due to trailing objects.<br>
+ void operator delete(void *p) { ::operator delete(p); }<br>
+<br>
+ static bool classof(const Init *I) {<br>
+ return I->getKind() == IK_VarDefInit;<br>
+ }<br>
+ static VarDefInit *get(Record *Class, ArrayRef<Init *> Args);<br>
+<br>
+ void Profile(FoldingSetNodeID &ID) const;<br>
+<br>
+ Init *resolveReferences(Resolver &R) const override;<br>
+ Init *Fold() const;<br>
+<br>
+ std::string getAsString() const override;<br>
+<br>
+ Init *getArg(unsigned i) const {<br>
+ assert(i < NumArgs && "Argument index out of range!");<br>
+ return getTrailingObjects<Init *>()[i];<br>
+ }<br>
+<br>
+ using const_iterator = Init *const *;<br>
+<br>
+ const_iterator args_begin() const { return getTrailingObjects<Init *>(); }<br>
+ const_iterator args_end () const { return args_begin() + NumArgs; }<br>
+<br>
+ size_t args_size () const { return NumArgs; }<br>
+ bool args_empty() const { return NumArgs == 0; }<br>
+<br>
+ ArrayRef<Init *> args() const { return makeArrayRef(args_begin(), NumArgs); }<br>
+<br>
+ Init *getBit(unsigned Bit) const override {<br>
+ llvm_unreachable("Illegal bit reference off anonymous def");<br>
+ }<br>
+};<br>
+<br>
/// X.Y - Represent a reference to a subfield of a variable<br>
class FieldInit : public TypedInit {<br>
Init *Rec; // Record we are referring to<br>
@@ -1754,6 +1807,21 @@ public:<br>
}<br>
};<br>
<br>
+/// (Optionally) delegate resolving to a sub-resolver, and keep track whether<br>
+/// there were unresolved references.<br>
+class TrackUnresolvedResolver final : public Resolver {<br>
+ Resolver *R;<br>
+ bool FoundUnresolved = false;<br>
+<br>
+public:<br>
+ explicit TrackUnresolvedResolver(<wbr>Resolver *R = nullptr)<br>
+ : Resolver(R ? R->getCurrentRecord() : nullptr), R(R) {}<br>
+<br>
+ bool foundUnresolved() const { return FoundUnresolved; }<br>
+<br>
+ Init *resolve(Init *VarName) override;<br>
+};<br>
+<br>
} // end namespace llvm<br>
<br>
#endif // LLVM_TABLEGEN_RECORD_H<br>
<br>
Modified: llvm/trunk/lib/TableGen/<wbr>Record.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/Record.cpp?rev=326788&r1=326787&r2=326788&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>TableGen/Record.cpp?rev=<wbr>326788&r1=326787&r2=326788&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/TableGen/<wbr>Record.cpp (original)<br>
+++ llvm/trunk/lib/TableGen/<wbr>Record.cpp Tue Mar 6 05:49:01 2018<br>
@@ -1355,6 +1355,132 @@ std::string DefInit::getAsString() const<br>
return Def->getName();<br>
}<br>
<br>
+static void ProfileVarDefInit(<wbr>FoldingSetNodeID &ID,<br>
+ Record *Class,<br>
+ ArrayRef<Init *> Args) {<br>
+ ID.AddInteger(Args.size());<br>
+ ID.AddPointer(Class);<br>
+<br>
+ for (Init *I : Args)<br>
+ ID.AddPointer(I);<br>
+}<br>
+<br>
+VarDefInit *VarDefInit::get(Record *Class, ArrayRef<Init *> Args) {<br>
+ static FoldingSet<VarDefInit> ThePool;<br>
+<br>
+ FoldingSetNodeID ID;<br>
+ ProfileVarDefInit(ID, Class, Args);<br>
+<br>
+ void *IP = nullptr;<br>
+ if (VarDefInit *I = ThePool.FindNodeOrInsertPos(<wbr>ID, IP))<br>
+ return I;<br>
+<br>
+ void *Mem = Allocator.Allocate(<wbr>totalSizeToAlloc<Init *>(Args.size()),<br>
+ alignof(VarDefInit));<br>
+ VarDefInit *I = new(Mem) VarDefInit(Class, Args.size());<br>
+ std::uninitialized_copy(Args.<wbr>begin(), Args.end(),<br>
+ I->getTrailingObjects<Init *>());<br>
+ ThePool.InsertNode(I, IP);<br>
+ return I;<br>
+}<br>
+<br>
+void VarDefInit::Profile(<wbr>FoldingSetNodeID &ID) const {<br>
+ ProfileVarDefInit(ID, Class, args());<br>
+}<br>
+<br>
+DefInit *VarDefInit::instantiate() {<br>
+ if (!Def) {<br>
+ RecordKeeper &Records = Class->getRecords();<br>
+ auto NewRecOwner = make_unique<Record>(Records.<wbr>getNewAnonymousName(),<br>
+ Class->getLoc(), Records,<br>
+ /*IsAnonymous=*/true);<br>
+ Record *NewRec = NewRecOwner.get();<br>
+<br>
+ // Copy values from class to instance<br>
+ for (const RecordVal &Val : Class->getValues()) {<br>
+ if (Val.getName() != "NAME")<br>
+ NewRec->addValue(Val);<br>
+ }<br>
+<br>
+ // Substitute and resolve template arguments<br>
+ ArrayRef<Init *> TArgs = Class->getTemplateArgs();<br>
+ MapResolver R(NewRec);<br>
+<br>
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {<br>
+ if (i < args_size())<br>
+ R.set(TArgs[i], getArg(i));<br>
+ else<br>
+ R.set(TArgs[i], NewRec->getValue(TArgs[i])-><wbr>getValue());<br>
+<br>
+ NewRec->removeValue(TArgs[i]);<br>
+ }<br>
+<br>
+ NewRec->resolveReferences(R);<br>
+<br>
+ // Add superclasses.<br>
+ ArrayRef<std::pair<Record *, SMRange>> SCs = Class->getSuperClasses();<br>
+ for (const auto &SCPair : SCs)<br>
+ NewRec->addSuperClass(SCPair.<wbr>first, SCPair.second);<br>
+<br>
+ NewRec->addSuperClass(Class,<br>
+ SMRange(Class->getLoc().back()<wbr>,<br>
+ Class->getLoc().back()));<br>
+<br>
+ // Resolve internal references and store in record keeper<br>
+ NewRec->resolveReferences();<br>
+ Records.addDef(std::move(<wbr>NewRecOwner));<br>
+<br>
+ Def = DefInit::get(NewRec);<br>
+ }<br>
+<br>
+ return Def;<br>
+}<br>
+<br>
+Init *VarDefInit::<wbr>resolveReferences(Resolver &R) const {<br>
+ TrackUnresolvedResolver UR(&R);<br>
+ bool Changed = false;<br>
+ SmallVector<Init *, 8> NewArgs;<br>
+ NewArgs.reserve(args_size());<br>
+<br>
+ for (Init *Arg : args()) {<br>
+ Init *NewArg = Arg->resolveReferences(UR);<br>
+ NewArgs.push_back(NewArg);<br>
+ Changed |= NewArg != Arg;<br>
+ }<br>
+<br>
+ if (Changed) {<br>
+ auto New = VarDefInit::get(Class, NewArgs);<br>
+ if (!UR.foundUnresolved())<br>
+ return New->instantiate();<br>
+ return New;<br>
+ }<br>
+ return const_cast<VarDefInit *>(this);<br>
+}<br>
+<br>
+Init *VarDefInit::Fold() const {<br>
+ if (Def)<br>
+ return Def;<br>
+<br>
+ TrackUnresolvedResolver R;<br>
+ for (Init *Arg : args())<br>
+ Arg->resolveReferences(R);<br>
+<br>
+ if (!R.foundUnresolved())<br>
+ return const_cast<VarDefInit *>(this)->instantiate();<br>
+ return const_cast<VarDefInit *>(this);<br>
+}<br>
+<br>
+std::string VarDefInit::getAsString() const {<br>
+ std::string Result = Class->getNameInitAsString() + "<";<br>
+ const char *sep = "";<br>
+ for (Init *Arg : args()) {<br>
+ Result += sep;<br>
+ sep = ", ";<br>
+ Result += Arg->getAsString();<br>
+ }<br>
+ return Result + ">";<br>
+}<br>
+<br>
FieldInit *FieldInit::get(Init *R, StringInit *FN) {<br>
using Key = std::pair<Init *, StringInit *>;<br>
static DenseMap<Key, FieldInit*> ThePool;<br>
@@ -1917,3 +2043,23 @@ Init *RecordResolver::resolve(Init *VarN<br>
Cache[VarName] = Val;<br>
return Val;<br>
}<br>
+<br>
+Init *TrackUnresolvedResolver::<wbr>resolve(Init *VarName) {<br>
+ Init *I = nullptr;<br>
+<br>
+ if (R) {<br>
+ I = R->resolve(VarName);<br>
+ if (I && !FoundUnresolved) {<br>
+ // Do not recurse into the resolved initializer, as that would change<br>
+ // the behavior of the resolver we're delegating, but do check to see<br>
+ // if there are unresolved variables remaining.<br>
+ TrackUnresolvedResolver Sub;<br>
+ I->resolveReferences(Sub);<br>
+ FoundUnresolved |= Sub.FoundUnresolved;<br>
+ }<br>
+ }<br>
+<br>
+ if (!I)<br>
+ FoundUnresolved = true;<br>
+ return I;<br>
+}<br>
<br>
Modified: llvm/trunk/lib/TableGen/<wbr>TGParser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.cpp?rev=326788&r1=326787&r2=326788&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>TableGen/TGParser.cpp?rev=<wbr>326788&r1=326787&r2=326788&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/TableGen/<wbr>TGParser.cpp (original)<br>
+++ llvm/trunk/lib/TableGen/<wbr>TGParser.cpp Tue Mar 6 05:49:01 2018<br>
@@ -1346,61 +1346,49 @@ Init *TGParser::ParseSimpleValue(<wbr>Record<br>
return nullptr;<br>
}<br>
<br>
- SubClassReference SCRef;<br>
- ParseValueList(SCRef.<wbr>TemplateArgs, CurRec, Class);<br>
- if (SCRef.TemplateArgs.empty()) return nullptr;<br>
+ SmallVector<Init *, 8> Args;<br>
+ ParseValueList(Args, CurRec, Class);<br>
+ if (Args.empty()) return nullptr;<br>
<br>
if (Lex.getCode() != tgtok::greater) {<br>
TokError("expected '>' at end of value list");<br>
return nullptr;<br>
}<br>
Lex.Lex(); // eat the '>'<br>
- SMLoc EndLoc = Lex.getLoc();<br>
<br>
- // Create the new record, set it as CurRec temporarily.<br>
- auto NewRecOwner =<br>
- make_unique<Record>(Records.<wbr>getNewAnonymousName(), NameLoc, Records,<br>
- /*IsAnonymous=*/true);<br>
- Record *NewRec = NewRecOwner.get(); // Keep a copy since we may release.<br>
- SCRef.RefRange = SMRange(NameLoc, EndLoc);<br>
- SCRef.Rec = Class;<br>
- // Add info about the subclass to NewRec.<br>
- if (AddSubClass(NewRec, SCRef))<br>
+ // Typecheck the template arguments list<br>
+ ArrayRef<Init *> ExpectedArgs = Class->getTemplateArgs();<br>
+ if (ExpectedArgs.size() < Args.size()) {<br>
+ Error(NameLoc,<br>
+ "More template args specified than expected");<br>
return nullptr;<br>
+ }<br>
<br>
- if (!CurMultiClass) {<br>
- NewRec->resolveReferences();<br>
- Records.addDef(std::move(<wbr>NewRecOwner));<br>
- } else {<br>
- // This needs to get resolved once the multiclass template arguments are<br>
- // known before any use.<br>
- NewRec->setResolveFirst(true);<br>
- // Otherwise, we're inside a multiclass, add it to the multiclass.<br>
- CurMultiClass->DefPrototypes.<wbr>push_back(std::move(<wbr>NewRecOwner));<br>
-<br>
- // Copy the template arguments for the multiclass into the def.<br>
- for (Init *TArg : CurMultiClass->Rec.<wbr>getTemplateArgs()) {<br>
- const RecordVal *RV = CurMultiClass->Rec.getValue(<wbr>TArg);<br>
- assert(RV && "Template arg doesn't exist?");<br>
- NewRec->addValue(*RV);<br>
- }<br>
-<br>
- // We can't return the prototype def here, instead return:<br>
- // !cast<ItemType>(!strconcat(<wbr>NAME, AnonName)).<br>
- const RecordVal *MCNameRV = CurMultiClass->Rec.getValue("<wbr>NAME");<br>
- assert(MCNameRV && "multiclass record must have a NAME");<br>
-<br>
- return UnOpInit::get(UnOpInit::CAST,<br>
- BinOpInit::get(BinOpInit::<wbr>STRCONCAT,<br>
- VarInit::get(MCNameRV-><wbr>getName(),<br>
- MCNameRV->getType()),<br>
- NewRec->getNameInit(),<br>
- StringRecTy::get()),<br>
- NewRec->getDefInit()->getType(<wbr>));<br>
+ for (unsigned i = 0, e = ExpectedArgs.size(); i != e; ++i) {<br>
+ RecordVal *ExpectedArg = Class->getValue(ExpectedArgs[<wbr>i]);<br>
+ if (i < Args.size()) {<br>
+ if (TypedInit *TI = dyn_cast<TypedInit>(Args[i])) {<br>
+ RecTy *ExpectedType = ExpectedArg->getType();<br>
+ if (!TI->getType()-><wbr>typeIsConvertibleTo(<wbr>ExpectedType)) {<br>
+ Error(NameLoc,<br>
+ "Value specified for template argument #" + Twine(i) + " (" +<br>
+ ExpectedArg-><wbr>getNameInitAsString() + ") is of type '" +<br>
+ TI->getType()->getAsString() + "', expected '" +<br>
+ ExpectedType->getAsString() + "': " + TI->getAsString());<br>
+ return nullptr;<br>
+ }<br>
+ continue;<br>
+ }<br>
+ } else if (ExpectedArg->getValue()-><wbr>isComplete())<br>
+ continue;<br>
+<br>
+ Error(NameLoc,<br>
+ "Value not specified for template argument #" + Twine(i) + " (" +<br>
+ ExpectedArgs[i]-><wbr>getAsUnquotedString() + ")");<br>
+ return nullptr;<br>
}<br>
<br>
- // The result of the expression is a reference to the new record.<br>
- return DefInit::get(NewRec);<br>
+ return VarDefInit::get(Class, Args)->Fold();<br>
}<br>
case tgtok::l_brace: { // Value ::= '{' ValueList '}'<br>
SMLoc BraceLoc = Lex.getLoc();<br>
<br>
Modified: llvm/trunk/test/TableGen/<wbr>AnonDefinitionOnDemand.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/AnonDefinitionOnDemand.td?rev=326788&r1=326787&r2=326788&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>TableGen/<wbr>AnonDefinitionOnDemand.td?rev=<wbr>326788&r1=326787&r2=326788&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/TableGen/<wbr>AnonDefinitionOnDemand.td (original)<br>
+++ llvm/trunk/test/TableGen/<wbr>AnonDefinitionOnDemand.td Tue Mar 6 05:49:01 2018<br>
@@ -1,6 +1,24 @@<br>
-// RUN: llvm-tblgen < %s<br>
+// RUN: llvm-tblgen %s | FileCheck %s<br>
// XFAIL: vg_leak<br>
<br>
+// CHECK: --- Defs ---<br>
+<br>
+// CHECK: def X {<br>
+// CHECK: foo Y = anonymous_0;<br>
+// CHECK: }<br>
+<br>
+// CHECK: def ZD {<br>
+// CHECK: foo Z = anonymous_1;<br>
+// CHECK: }<br>
+<br>
+// CHECK: def anonymous_0 {<br>
+// CHECK: int THEVAL = 1;<br>
+// CHECK: }<br>
+<br>
+// CHECK: def anonymous_1 {<br>
+// CHECK: int THEVAL = 42;<br>
+// CHECK: }<br>
+<br>
class foo<int X> { int THEVAL = X; }<br>
def foo_imp : foo<1>;<br>
<br>
@@ -11,3 +29,9 @@ def x {<br>
def X {<br>
foo Y = foo<1>; // This should work too, synthesizing a new foo<1>.<br>
}<br>
+<br>
+class Z<int X> {<br>
+ foo Z = foo<X>;<br>
+}<br>
+<br>
+def ZD : Z<42>;<br>
<br>
<br>
______________________________<wbr>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>