<div dir="ltr"><a href="http://build.chromium.org/p/chromium.fyi/builders/CrWinClang%28dbg%29/builds/0/steps/compile/logs/stdio">http://build.chromium.org/p/chromium.fyi/builders/CrWinClang%28dbg%29/builds/0/steps/compile/logs/stdio</a> has many `Assertion failed: Val && "isa<> used on a null pointer"` that used to not be there, and this change added an isa<>() call. Maybe it's related?<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Mar 17, 2015 at 3:00 PM, Reid Kleckner <span dir="ltr"><<a href="mailto:reid@kleckner.net" target="_blank">reid@kleckner.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rnk<br>
Date: Tue Mar 17 14:00:50 2015<br>
New Revision: 232519<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=232519&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=232519&view=rev</a><br>
Log:<br>
MS ABI: Delay default constructor closure checking until the outermost class scope ends<br>
<br>
Previously, we would error out on this code because the default argument<br>
wasn't parsed until the end of Outer:<br>
<br>
struct __declspec(dllexport) Outer {<br>
struct __declspec(dllexport) Inner {<br>
Inner(void *p = 0);<br>
};<br>
};<br>
<br>
Now we do the checking on the closing brace of Outer instead of Inner.<br>
<br>
Modified:<br>
cfe/trunk/include/clang/Sema/Sema.h<br>
cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp<br>
cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br>
cfe/trunk/lib/Sema/SemaDecl.cpp<br>
cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
cfe/trunk/test/CodeGenCXX/dllexport.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=232519&r1=232518&r2=232519&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=232519&r1=232518&r2=232519&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Mar 17 14:00:50 2015<br>
@@ -5012,6 +5012,7 @@ public:<br>
SourceLocation RBrac,<br>
AttributeList *AttrList);<br>
void ActOnFinishCXXMemberDecls();<br>
+ void ActOnFinishCXXMethodDefs(Decl *D);<br>
<br>
void ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param);<br>
unsigned ActOnReenterTemplateScope(Scope *S, Decl *Template);<br>
<br>
Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=232519&r1=232518&r2=232519&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=232519&r1=232518&r2=232519&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Tue Mar 17 14:00:50 2015<br>
@@ -3309,6 +3309,8 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure<br>
QualType RecordTy = getContext().getRecordType(RD);<br>
llvm::Function *ThunkFn = llvm::Function::Create(<br>
ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.getModule());<br>
+ ThunkFn->setCallingConv(static_cast<llvm::CallingConv::ID>(<br>
+ FnInfo.getEffectiveCallingConvention()));<br>
bool IsCopy = CT == Ctor_CopyingClosure;<br>
<br>
// Start codegen.<br>
<br>
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=232519&r1=232518&r2=232519&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=232519&r1=232518&r2=232519&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Mar 17 14:00:50 2015<br>
@@ -2915,6 +2915,10 @@ void Parser::ParseCXXMemberSpecification<br>
ParseLexedMemberInitializers(getCurrentClass());<br>
ParseLexedMethodDefs(getCurrentClass());<br>
PrevTokLocation = SavedPrevTokLocation;<br>
+<br>
+ // We've finished parsing everything, including default argument<br>
+ // initializers.<br>
+ Actions.ActOnFinishCXXMethodDefs(TagDecl);<br>
}<br>
<br>
if (TagDecl)<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=232519&r1=232518&r2=232519&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=232519&r1=232518&r2=232519&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Mar 17 14:00:50 2015<br>
@@ -12067,24 +12067,6 @@ void Sema::ActOnStartCXXMemberDeclaratio<br>
"Broken injected-class-name");<br>
}<br>
<br>
-static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) {<br>
- for (Decl *Member : Class->decls()) {<br>
- auto *CD = dyn_cast<CXXConstructorDecl>(Member);<br>
- if (!CD || !CD->isDefaultConstructor() || !CD->hasAttr<DLLExportAttr>())<br>
- continue;<br>
-<br>
- for (unsigned I = 0, E = CD->getNumParams(); I != E; ++I) {<br>
- // Skip any default arguments that we've already instantiated.<br>
- if (S.Context.getDefaultArgExprForConstructor(CD, I))<br>
- continue;<br>
-<br>
- Expr *DefaultArg = S.BuildCXXDefaultArgExpr(Class->getLocation(), CD,<br>
- CD->getParamDecl(I)).get();<br>
- S.Context.addDefaultArgExprForConstructor(CD, I, DefaultArg);<br>
- }<br>
- }<br>
-}<br>
-<br>
void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD,<br>
SourceLocation RBraceLoc) {<br>
AdjustDeclIfTemplate(TagD);<br>
@@ -12098,17 +12080,9 @@ void Sema::ActOnTagFinishDefinition(Scop<br>
RD->completeDefinition();<br>
}<br>
<br>
- if (auto *Class = dyn_cast<CXXRecordDecl>(Tag)) {<br>
+ if (isa<CXXRecordDecl>(Tag))<br>
FieldCollector->FinishClass();<br>
<br>
- // Default constructors that are annotated with __declspec(dllexport) which<br>
- // have default arguments or don't use the standard calling convention are<br>
- // wrapped with a thunk called the default constructor closure.<br>
- if (!Class->getDescribedClassTemplate() &&<br>
- Context.getTargetInfo().getCXXABI().isMicrosoft())<br>
- getDefaultArgExprsForConstructors(*this, Class);<br>
- }<br>
-<br>
// Exit this scope of this tag's definition.<br>
PopDeclContext();<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=232519&r1=232518&r2=232519&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=232519&r1=232518&r2=232519&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Mar 17 14:00:50 2015<br>
@@ -9421,6 +9421,44 @@ void Sema::ActOnFinishCXXMemberDecls() {<br>
}<br>
}<br>
<br>
+static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) {<br>
+ // Don't do anything for template patterns.<br>
+ if (Class->getDescribedClassTemplate())<br>
+ return;<br>
+<br>
+ for (Decl *Member : Class->decls()) {<br>
+ auto *CD = dyn_cast<CXXConstructorDecl>(Member);<br>
+ if (!CD) {<br>
+ // Recurse on nested classes.<br>
+ if (auto *NestedRD = dyn_cast<CXXRecordDecl>(Member))<br>
+ getDefaultArgExprsForConstructors(S, NestedRD);<br>
+ continue;<br>
+ } else if (!CD->isDefaultConstructor() || !CD->hasAttr<DLLExportAttr>()) {<br>
+ continue;<br>
+ }<br>
+<br>
+ for (unsigned I = 0, E = CD->getNumParams(); I != E; ++I) {<br>
+ // Skip any default arguments that we've already instantiated.<br>
+ if (S.Context.getDefaultArgExprForConstructor(CD, I))<br>
+ continue;<br>
+<br>
+ Expr *DefaultArg = S.BuildCXXDefaultArgExpr(Class->getLocation(), CD,<br>
+ CD->getParamDecl(I)).get();<br>
+ S.Context.addDefaultArgExprForConstructor(CD, I, DefaultArg);<br>
+ }<br>
+ }<br>
+}<br>
+<br>
+void Sema::ActOnFinishCXXMethodDefs(Decl *D) {<br>
+ auto *RD = dyn_cast<CXXRecordDecl>(D);<br>
+<br>
+ // Default constructors that are annotated with __declspec(dllexport) which<br>
+ // have default arguments or don't use the standard calling convention are<br>
+ // wrapped with a thunk called the default constructor closure.<br>
+ if (RD && Context.getTargetInfo().getCXXABI().isMicrosoft())<br>
+ getDefaultArgExprsForConstructors(*this, RD);<br>
+}<br>
+<br>
void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,<br>
CXXDestructorDecl *Destructor) {<br>
assert(getLangOpts().CPlusPlus11 &&<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/dllexport.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport.cpp?rev=232519&r1=232518&r2=232519&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport.cpp?rev=232519&r1=232518&r2=232519&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/dllexport.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/dllexport.cpp Tue Mar 17 14:00:50 2015<br>
@@ -486,7 +486,7 @@ struct S {<br>
<br>
struct CtorWithClosure {<br>
__declspec(dllexport) CtorWithClosure(...) {}<br>
-// M32-DAG: define weak_odr dllexport void @"\01??_FCtorWithClosure@@QAEXXZ"<br>
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FCtorWithClosure@@QAEXXZ"<br>
// M32-DAG: %[[this_addr:.*]] = alloca %struct.CtorWithClosure*, align 4<br>
// M32-DAG: store %struct.CtorWithClosure* %this, %struct.CtorWithClosure** %[[this_addr]], align 4<br>
// M32-DAG: %[[this:.*]] = load %struct.CtorWithClosure*, %struct.CtorWithClosure** %[[this_addr]]<br>
@@ -494,12 +494,16 @@ struct CtorWithClosure {<br>
// M32-DAG: ret void<br>
};<br>
<br>
+#define DELETE_IMPLICIT_MEMBERS(ClassName) \<br>
+ ClassName(ClassName &&) = delete; \<br>
+ ClassName(ClassName &) = delete; \<br>
+ ~ClassName() = delete; \<br>
+ ClassName &operator=(ClassName &) = delete<br>
+<br>
struct __declspec(dllexport) ClassWithClosure {<br>
- ClassWithClosure(ClassWithClosure &&) = delete;<br>
- ClassWithClosure(ClassWithClosure &) = delete;<br>
- ~ClassWithClosure() = delete;<br>
+ DELETE_IMPLICIT_MEMBERS(ClassWithClosure);<br>
ClassWithClosure(...) {}<br>
-// M32-DAG: define weak_odr dllexport void @"\01??_FClassWithClosure@@QAEXXZ"<br>
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FClassWithClosure@@QAEXXZ"<br>
// M32-DAG: %[[this_addr:.*]] = alloca %struct.ClassWithClosure*, align 4<br>
// M32-DAG: store %struct.ClassWithClosure* %this, %struct.ClassWithClosure** %[[this_addr]], align 4<br>
// M32-DAG: %[[this:.*]] = load %struct.ClassWithClosure*, %struct.ClassWithClosure** %[[this_addr]]<br>
@@ -507,6 +511,18 @@ struct __declspec(dllexport) ClassWithCl<br>
// M32-DAG: ret void<br>
};<br>
<br>
+struct __declspec(dllexport) NestedOuter {<br>
+ DELETE_IMPLICIT_MEMBERS(NestedOuter);<br>
+ NestedOuter(void *p = 0) {}<br>
+ struct __declspec(dllexport) NestedInner {<br>
+ DELETE_IMPLICIT_MEMBERS(NestedInner);<br>
+ NestedInner(void *p = 0) {}<br>
+ };<br>
+};<br>
+<br>
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FNestedOuter@@QAEXXZ"<br>
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FNestedInner@NestedOuter@@QAEXXZ"<br>
+<br>
struct __declspec(dllexport) T {<br>
// Copy assignment operator:<br>
// M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@ABU0@@Z"<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>