Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.

We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.

When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.

Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.

Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.

This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154886 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 8fe28e9..f0f52c7 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -125,14 +125,17 @@
   }
 }
 
-void Sema::ImplicitExceptionSpecification::CalledDecl(CXXMethodDecl *Method) {
-  assert(Context && "ImplicitExceptionSpecification without an ASTContext");
+void Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
+                                                      CXXMethodDecl *Method) {
   // If we have an MSAny or unknown spec already, don't bother.
   if (!Method || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed)
     return;
 
   const FunctionProtoType *Proto
     = Method->getType()->getAs<FunctionProtoType>();
+  Proto = Self->ResolveExceptionSpec(CallLoc, Proto);
+  if (!Proto)
+    return;
 
   ExceptionSpecificationType EST = Proto->getExceptionSpecType();
 
@@ -164,7 +167,8 @@
 
   // Check out noexcept specs.
   if (EST == EST_ComputedNoexcept) {
-    FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(*Context);
+    FunctionProtoType::NoexceptResult NR =
+        Proto->getNoexceptSpec(Self->Context);
     assert(NR != FunctionProtoType::NR_NoNoexcept &&
            "Must have noexcept result for EST_ComputedNoexcept.");
     assert(NR != FunctionProtoType::NR_Dependent &&
@@ -188,7 +192,7 @@
   for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
                                           EEnd = Proto->exception_end();
        E != EEnd; ++E)
-    if (ExceptionsSeen.insert(Context->getCanonicalType(*E)))
+    if (ExceptionsSeen.insert(Self->Context.getCanonicalType(*E)))
       Exceptions.push_back(*E);
 }
 
@@ -217,7 +221,7 @@
   // implicit definition. For now, we assume that any non-nothrow expression can
   // throw any exception.
 
-  if (E->CanThrow(*Context))
+  if (Self->canThrow(E))
     ComputedEST = EST_None;
 }
 
@@ -3922,7 +3926,7 @@
     HadError = true;
   }
 
-  ImplicitExceptionSpecification Spec(Context);
+  ImplicitExceptionSpecification Spec(*this);
   bool Const;
   llvm::tie(Spec, Const) =
     ComputeDefaultedCopyCtorExceptionSpecAndConst(CD->getParent());
@@ -4031,7 +4035,7 @@
     HadError = true;
   }
 
-  ImplicitExceptionSpecification Spec(Context);
+  ImplicitExceptionSpecification Spec(*this);
   bool Const;
   llvm::tie(Spec, Const) =
     ComputeDefaultedCopyCtorExceptionSpecAndConst(MD->getParent());
@@ -6814,7 +6818,7 @@
   // C++ [except.spec]p14:
   //   An implicitly declared special member function (Clause 12) shall have an 
   //   exception-specification. [...]
-  ImplicitExceptionSpecification ExceptSpec(Context);
+  ImplicitExceptionSpecification ExceptSpec(*this);
   if (ClassDecl->isInvalidDecl())
     return ExceptSpec;
 
@@ -6831,7 +6835,7 @@
       // If this is a deleted function, add it anyway. This might be conformant
       // with the standard. This might not. I'm not sure. It might not matter.
       if (Constructor)
-        ExceptSpec.CalledDecl(Constructor);
+        ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
     }
   }
 
@@ -6845,7 +6849,7 @@
       // If this is a deleted function, add it anyway. This might be conformant
       // with the standard. This might not. I'm not sure. It might not matter.
       if (Constructor)
-        ExceptSpec.CalledDecl(Constructor);
+        ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
     }
   }
 
@@ -6868,7 +6872,7 @@
       // might just be ill-formed because this function attempts to refer to
       // a deleted function here.
       if (Constructor)
-        ExceptSpec.CalledDecl(Constructor);
+        ExceptSpec.CalledDecl(F->getLocation(), Constructor);
     }
   }
 
@@ -6990,6 +6994,7 @@
   const FunctionProtoType *CtorTy =
     CtorDecl->getType()->castAs<FunctionProtoType>();
   if (CtorTy->getExceptionSpecType() == EST_Delayed) {
+    // FIXME: Don't do this unless the exception spec is needed.
     ImplicitExceptionSpecification Spec = 
       ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl);
     FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
@@ -7190,7 +7195,7 @@
   // C++ [except.spec]p14: 
   //   An implicitly declared special member function (Clause 12) shall have 
   //   an exception-specification.
-  ImplicitExceptionSpecification ExceptSpec(Context);
+  ImplicitExceptionSpecification ExceptSpec(*this);
   if (ClassDecl->isInvalidDecl())
     return ExceptSpec;
 
@@ -7202,7 +7207,7 @@
       continue;
     
     if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
-      ExceptSpec.CalledDecl(
+      ExceptSpec.CalledDecl(B->getLocStart(),
                    LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
   }
 
@@ -7211,7 +7216,7 @@
                                        BEnd = ClassDecl->vbases_end();
        B != BEnd; ++B) {
     if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
-      ExceptSpec.CalledDecl(
+      ExceptSpec.CalledDecl(B->getLocStart(),
                   LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
   }
 
@@ -7221,7 +7226,7 @@
        F != FEnd; ++F) {
     if (const RecordType *RecordTy
         = Context.getBaseElementType(F->getType())->getAs<RecordType>())
-      ExceptSpec.CalledDecl(
+      ExceptSpec.CalledDecl(F->getLocation(),
                   LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));
   }
 
@@ -7546,7 +7551,7 @@
 Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
                                                    CXXRecordDecl *ClassDecl) {
   if (ClassDecl->isInvalidDecl())
-    return std::make_pair(ImplicitExceptionSpecification(Context), false);
+    return std::make_pair(ImplicitExceptionSpecification(*this), false);
 
   // C++ [class.copy]p10:
   //   If the class definition does not explicitly declare a copy
@@ -7619,7 +7624,7 @@
   // Based on a similar decision made for constness in C++0x, we're erring on
   // the side of assuming such calls to be made regardless of whether they
   // actually happen.
-  ImplicitExceptionSpecification ExceptSpec(Context);
+  ImplicitExceptionSpecification ExceptSpec(*this);
   unsigned ArgQuals = HasConstCopyAssignment ? Qualifiers::Const : 0;
   for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
                                        BaseEnd = ClassDecl->bases_end();
@@ -7631,7 +7636,7 @@
       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
     if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
                                                             ArgQuals, false, 0))
-      ExceptSpec.CalledDecl(CopyAssign);
+      ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign);
   }
 
   for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
@@ -7641,7 +7646,7 @@
       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
     if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
                                                             ArgQuals, false, 0))
-      ExceptSpec.CalledDecl(CopyAssign);
+      ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign);
   }
 
   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
@@ -7652,7 +7657,7 @@
     if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
       if (CXXMethodDecl *CopyAssign =
           LookupCopyingAssignment(FieldClassDecl, ArgQuals, false, 0))
-        ExceptSpec.CalledDecl(CopyAssign);
+        ExceptSpec.CalledDecl(Field->getLocation(), CopyAssign);
     }
   }
 
@@ -7665,7 +7670,7 @@
   // for determining the argument type of the operator. Note also that
   // operators taking an object instead of a reference are allowed.
 
-  ImplicitExceptionSpecification Spec(Context);
+  ImplicitExceptionSpecification Spec(*this);
   bool Const;
   llvm::tie(Spec, Const) =
     ComputeDefaultedCopyAssignmentExceptionSpecAndConst(ClassDecl);
@@ -8032,7 +8037,7 @@
 
 Sema::ImplicitExceptionSpecification
 Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) {
-  ImplicitExceptionSpecification ExceptSpec(Context);
+  ImplicitExceptionSpecification ExceptSpec(*this);
 
   if (ClassDecl->isInvalidDecl())
     return ExceptSpec;
@@ -8059,7 +8064,7 @@
       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
     if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
                                                            false, 0))
-      ExceptSpec.CalledDecl(MoveAssign);
+      ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
   }
 
   for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
@@ -8069,7 +8074,7 @@
       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
     if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
                                                            false, 0))
-      ExceptSpec.CalledDecl(MoveAssign);
+      ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
   }
 
   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
@@ -8080,7 +8085,7 @@
     if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
       if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(FieldClassDecl,
                                                              false, 0))
-        ExceptSpec.CalledDecl(MoveAssign);
+        ExceptSpec.CalledDecl(Field->getLocation(), MoveAssign);
     }
   }
 
@@ -8578,7 +8583,7 @@
 std::pair<Sema::ImplicitExceptionSpecification, bool>
 Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {
   if (ClassDecl->isInvalidDecl())
-    return std::make_pair(ImplicitExceptionSpecification(Context), false);
+    return std::make_pair(ImplicitExceptionSpecification(*this), false);
 
   // C++ [class.copy]p5:
   //   The implicitly-declared copy constructor for a class X will
@@ -8639,7 +8644,7 @@
   // C++ [except.spec]p14:
   //   An implicitly declared special member function (Clause 12) shall have an 
   //   exception-specification. [...]
-  ImplicitExceptionSpecification ExceptSpec(Context);
+  ImplicitExceptionSpecification ExceptSpec(*this);
   unsigned Quals = HasConstCopyConstructor? Qualifiers::Const : 0;
   for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
                                        BaseEnd = ClassDecl->bases_end();
@@ -8653,7 +8658,7 @@
       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
     if (CXXConstructorDecl *CopyConstructor =
           LookupCopyingConstructor(BaseClassDecl, Quals))
-      ExceptSpec.CalledDecl(CopyConstructor);
+      ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor);
   }
   for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
                                        BaseEnd = ClassDecl->vbases_end();
@@ -8663,7 +8668,7 @@
       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
     if (CXXConstructorDecl *CopyConstructor =
           LookupCopyingConstructor(BaseClassDecl, Quals))
-      ExceptSpec.CalledDecl(CopyConstructor);
+      ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor);
   }
   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
                                   FieldEnd = ClassDecl->field_end();
@@ -8673,7 +8678,7 @@
     if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
       if (CXXConstructorDecl *CopyConstructor =
         LookupCopyingConstructor(FieldClassDecl, Quals))
-      ExceptSpec.CalledDecl(CopyConstructor);
+      ExceptSpec.CalledDecl(Field->getLocation(), CopyConstructor);
     }
   }
 
@@ -8686,7 +8691,7 @@
   //   If the class definition does not explicitly declare a copy
   //   constructor, one is declared implicitly.
 
-  ImplicitExceptionSpecification Spec(Context);
+  ImplicitExceptionSpecification Spec(*this);
   bool Const;
   llvm::tie(Spec, Const) =
     ComputeDefaultedCopyCtorExceptionSpecAndConst(ClassDecl);
@@ -8784,7 +8789,7 @@
   // C++ [except.spec]p14:
   //   An implicitly declared special member function (Clause 12) shall have an 
   //   exception-specification. [...]
-  ImplicitExceptionSpecification ExceptSpec(Context);
+  ImplicitExceptionSpecification ExceptSpec(*this);
   if (ClassDecl->isInvalidDecl())
     return ExceptSpec;
 
@@ -8801,7 +8806,7 @@
       // If this is a deleted function, add it anyway. This might be conformant
       // with the standard. This might not. I'm not sure. It might not matter.
       if (Constructor)
-        ExceptSpec.CalledDecl(Constructor);
+        ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
     }
   }
 
@@ -8815,7 +8820,7 @@
       // If this is a deleted function, add it anyway. This might be conformant
       // with the standard. This might not. I'm not sure. It might not matter.
       if (Constructor)
-        ExceptSpec.CalledDecl(Constructor);
+        ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
     }
   }
 
@@ -8833,7 +8838,7 @@
       // might just be ill-formed because this function attempts to refer to
       // a deleted function here.
       if (Constructor)
-        ExceptSpec.CalledDecl(Constructor);
+        ExceptSpec.CalledDecl(F->getLocation(), Constructor);
     }
   }
 
@@ -11116,6 +11121,7 @@
   FindCXXThisExpr Finder(*this);
 
   switch (Proto->getExceptionSpecType()) {
+  case EST_Uninstantiated:
   case EST_BasicNoexcept:
   case EST_Delayed:
   case EST_DynamicNone: