Reject incomplete types in exception specs.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72580 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index 2a765d2..f3ff0c6 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -35,6 +35,7 @@
                                              bool hasExceptionSpec,
                                              bool hasAnyExceptionSpec,
                                              ActionBase::TypeTy **Exceptions,
+                                             SourceRange *ExceptionRanges,
                                              unsigned NumExceptions,
                                              SourceLocation Loc,
                                              Declarator &TheDeclarator) {
@@ -72,9 +73,11 @@
   }
   // new[] an exception array if needed
   if (NumExceptions) {
-    I.Fun.Exceptions = new ActionBase::TypeTy*[NumExceptions];
-    memcpy(I.Fun.Exceptions, Exceptions,
-           sizeof(ActionBase::TypeTy*)*NumExceptions);
+    I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions];
+    for (unsigned i = 0; i != NumExceptions; ++i) {
+      I.Fun.Exceptions[i].Ty = Exceptions[i];
+      I.Fun.Exceptions[i].Range = ExceptionRanges[i];
+    }
   }
   return I;
 }
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index b667014..36ebec3 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -27,15 +27,17 @@
 ///         specifier-qualifier-list abstract-declarator[opt]
 ///
 /// Called type-id in C++.
-Action::TypeResult Parser::ParseTypeName() {
+Action::TypeResult Parser::ParseTypeName(SourceRange *Range) {
   // Parse the common declaration-specifiers piece.
   DeclSpec DS;
   ParseSpecifierQualifierList(DS);
-  
+
   // Parse the abstract-declarator, if present.
   Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
   ParseDeclarator(DeclaratorInfo);
-  
+  if (Range)
+    *Range = DeclaratorInfo.getSourceRange();
+
   if (DeclaratorInfo.isInvalidType())
     return true;
 
@@ -2273,9 +2275,8 @@
     DeclSpec DS;
     bool hasExceptionSpec = false;
     bool hasAnyExceptionSpec = false;
-    // FIXME: Does an empty vector ever allocate? Exception specifications are
-    // extremely rare, so we want something like a SmallVector<TypeTy*, 0>. :-)
-    std::vector<TypeTy*> Exceptions;
+    llvm::SmallVector<TypeTy*, 2> Exceptions;
+    llvm::SmallVector<SourceRange, 2> ExceptionRanges;
     if (getLang().CPlusPlus) {
       ParseTypeQualifierListOpt(DS, false /*no attributes*/);
       if (!DS.getSourceRange().getEnd().isInvalid())
@@ -2284,7 +2285,10 @@
       // Parse exception-specification[opt].
       if (Tok.is(tok::kw_throw)) {
         hasExceptionSpec = true;
-        ParseExceptionSpecification(Loc, Exceptions, hasAnyExceptionSpec);
+        ParseExceptionSpecification(Loc, Exceptions, ExceptionRanges,
+                                    hasAnyExceptionSpec);
+        assert(Exceptions.size() == ExceptionRanges.size() &&
+               "Produced different number of exception types and ranges.");
       }
     }
 
@@ -2297,14 +2301,14 @@
                                                DS.getTypeQualifiers(),
                                                hasExceptionSpec,
                                                hasAnyExceptionSpec,
-                                               Exceptions.empty() ? 0 :
-                                                 &Exceptions[0],
+                                               Exceptions.data(),
+                                               ExceptionRanges.data(),
                                                Exceptions.size(),
                                                LParenLoc, D),
                   Loc);
     return;
-  } 
-  
+  }
+
   // Alternatively, this parameter list may be an identifier list form for a
   // K&R-style function:  void foo(a,b,c)
   if (!getLang().CPlusPlus && Tok.is(tok::identifier)) {
@@ -2445,9 +2449,8 @@
   DeclSpec DS;
   bool hasExceptionSpec = false;
   bool hasAnyExceptionSpec = false;
-  // FIXME: Does an empty vector ever allocate? Exception specifications are
-  // extremely rare, so we want something like a SmallVector<TypeTy*, 0>. :-)
-  std::vector<TypeTy*> Exceptions;
+  llvm::SmallVector<TypeTy*, 2> Exceptions;
+  llvm::SmallVector<SourceRange, 2> ExceptionRanges;
   if (getLang().CPlusPlus) {
     // Parse cv-qualifier-seq[opt].
     ParseTypeQualifierListOpt(DS, false /*no attributes*/);
@@ -2457,7 +2460,10 @@
     // Parse exception-specification[opt].
     if (Tok.is(tok::kw_throw)) {
       hasExceptionSpec = true;
-      ParseExceptionSpecification(Loc, Exceptions, hasAnyExceptionSpec);
+      ParseExceptionSpecification(Loc, Exceptions, ExceptionRanges,
+                                  hasAnyExceptionSpec);
+      assert(Exceptions.size() == ExceptionRanges.size() &&
+             "Produced different number of exception types and ranges.");
     }
   }
 
@@ -2468,8 +2474,8 @@
                                              DS.getTypeQualifiers(),
                                              hasExceptionSpec,
                                              hasAnyExceptionSpec,
-                                             Exceptions.empty() ? 0 :
-                                               &Exceptions[0],
+                                             Exceptions.data(),
+                                             ExceptionRanges.data(),
                                              Exceptions.size(), LParenLoc, D),
                 Loc);
 }
@@ -2545,7 +2551,7 @@
                                              SourceLocation(),
                                              &ParamInfo[0], ParamInfo.size(),
                                              /*TypeQuals*/0,
-                                             /*exception*/false, false, 0, 0,
+                                             /*exception*/false, false, 0, 0, 0,
                                              LParenLoc, D),
                 RLoc);
 }
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 7cbd72b..809dc10 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1191,7 +1191,10 @@
 ///         type-id-list ',' type-id
 ///
 bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc,
-                                         std::vector<TypeTy*> &Exceptions,
+                                         llvm::SmallVector<TypeTy*, 2>
+                                             &Exceptions,
+                                         llvm::SmallVector<SourceRange, 2>
+                                             &Ranges,
                                          bool &hasAnyExceptionSpec) {
   assert(Tok.is(tok::kw_throw) && "expected throw");
   
@@ -1214,10 +1217,13 @@
   }
 
   // Parse the sequence of type-ids.
+  SourceRange Range;
   while (Tok.isNot(tok::r_paren)) {
-    TypeResult Res(ParseTypeName());
-    if (!Res.isInvalid())
+    TypeResult Res(ParseTypeName(&Range));
+    if (!Res.isInvalid()) {
       Exceptions.push_back(Res.get());
+      Ranges.push_back(Range);
+    }
     if (Tok.is(tok::comma))
       ConsumeToken();
     else
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 5c06386..8b8d4e1 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1481,7 +1481,7 @@
     ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false, 
                                                        SourceLocation(),
                                                        0, 0, 0,
-                                                       false, false, 0, 0,
+                                                       false, false, 0, 0, 0,
                                                        CaretLoc, ParamInfo),
                           CaretLoc);