]> granicus.if.org Git - clang/commitdiff
If parsing a trailing-return-type fails, don't pretend we didn't have one at
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 12 Jun 2012 01:51:59 +0000 (01:51 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 12 Jun 2012 01:51:59 +0000 (01:51 +0000)
all. Suppresses follow-on errors mentioned in PR13074.

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

include/clang/Sema/DeclSpec.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseExprCXX.cpp
lib/Sema/DeclSpec.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaType.cpp
test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp
test/Parser/cxx11-type-specifier.cpp

index 422a17cc25b49ec6f293fb00ea26cd520c0952c7..6b52cd5e91e2b3d5ce434377c3ebe327524e0bde 100644 (file)
@@ -1104,6 +1104,10 @@ struct DeclaratorChunk {
     /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo.
     unsigned DeleteArgInfo : 1;
 
+    /// HasTrailingReturnType - If this is true, a trailing return type was
+    /// specified.
+    unsigned HasTrailingReturnType : 1;
+
     /// When isVariadic is true, the location of the ellipsis in the source.
     unsigned EllipsisLoc;
 
@@ -1154,10 +1158,9 @@ struct DeclaratorChunk {
       Expr *NoexceptExpr;
     };
 
-    /// TrailingReturnType - If this isn't null, it's the trailing return type
-    /// specified. This is actually a ParsedType, but stored as void* to
-    /// allow union storage.
-    void *TrailingReturnType;
+    /// TrailingReturnType - If HasTrailingReturnType is true, this is the
+    /// trailing return type specified.
+    UnionParsedType TrailingReturnType;
 
     /// freeArgs - reset the argument list to having zero arguments.  This is
     /// used in various places for error recovery.
@@ -1222,6 +1225,13 @@ struct DeclaratorChunk {
     ExceptionSpecificationType getExceptionSpecType() const {
       return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
     }
+
+    /// \brief Determine whether this function declarator had a
+    /// trailing-return-type.
+    bool hasTrailingReturnType() const { return HasTrailingReturnType; }
+
+    /// \brief Get the trailing-return-type for this function declarator.
+    ParsedType getTrailingReturnType() const { return TrailingReturnType; }
   };
 
   struct BlockPointerTypeInfo : TypeInfoCommon {
@@ -1352,8 +1362,8 @@ struct DeclaratorChunk {
                                      SourceLocation LocalRangeBegin,
                                      SourceLocation LocalRangeEnd,
                                      Declarator &TheDeclarator,
-                                     ParsedType TrailingReturnType =
-                                                    ParsedType());
+                                     TypeResult TrailingReturnType =
+                                                    TypeResult());
 
   /// getBlockPointer - Return a DeclaratorChunk for a block.
   ///
index ac6378035cf63b4ededb0ddac7e0494907c8cb6a..3eeef7bff34ced5e77ce6042702444358ba0c10b 100644 (file)
@@ -4276,7 +4276,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
   SmallVector<SourceRange, 2> DynamicExceptionRanges;
   ExprResult NoexceptExpr;
   ParsedAttributes FnAttrs(AttrFactory);
-  ParsedType TrailingReturnType;
+  TypeResult TrailingReturnType;
 
   Actions.ActOnStartFunctionDeclarator();
 
@@ -4358,7 +4358,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
       if (getLangOpts().CPlusPlus0x && Tok.is(tok::arrow)) {
         Diag(Tok, diag::warn_cxx98_compat_trailing_return_type);
         SourceRange Range;
-        TrailingReturnType = ParseTrailingReturnType(Range).get();
+        TrailingReturnType = ParseTrailingReturnType(Range);
         if (Range.getEnd().isValid())
           EndLoc = Range.getEnd();
       }
index 68eff7cf5f84ce030151143403ed63f069fd720b..1c7b56fd4d74c535d652fdde3f99dbf1b0ac02cd 100644 (file)
@@ -792,10 +792,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
     MaybeParseCXX0XAttributes(Attr, &DeclEndLoc);
 
     // Parse trailing-return-type[opt].
-    ParsedType TrailingReturnType;
+    TypeResult TrailingReturnType;
     if (Tok.is(tok::arrow)) {
       SourceRange Range;
-      TrailingReturnType = ParseTrailingReturnType(Range).get();
+      TrailingReturnType = ParseTrailingReturnType(Range);
       if (Range.getEnd().isValid())
         DeclEndLoc = Range.getEnd();
     }
@@ -838,10 +838,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
     }
     
     // Parse the return type, if there is one.
-    ParsedType TrailingReturnType;
+    TypeResult TrailingReturnType;
     if (Tok.is(tok::arrow)) {
       SourceRange Range;
-      TrailingReturnType = ParseTrailingReturnType(Range).get();
+      TrailingReturnType = ParseTrailingReturnType(Range);
       if (Range.getEnd().isValid())
         DeclEndLoc = Range.getEnd();      
     }
index 8ea72ca79ce58d4699aa37e47db8fd405ebc2c1f..f6764c2999454090afb7be3fbba6a5113b124f34 100644 (file)
@@ -165,7 +165,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
                                              SourceLocation LocalRangeBegin,
                                              SourceLocation LocalRangeEnd,
                                              Declarator &TheDeclarator,
-                                             ParsedType TrailingReturnType) {
+                                             TypeResult TrailingReturnType) {
   DeclaratorChunk I;
   I.Kind                        = Function;
   I.Loc                         = LocalRangeBegin;
@@ -188,7 +188,9 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
   I.Fun.NumExceptions           = 0;
   I.Fun.Exceptions              = 0;
   I.Fun.NoexceptExpr            = 0;
-  I.Fun.TrailingReturnType   = TrailingReturnType.getAsOpaquePtr();
+  I.Fun.HasTrailingReturnType   = TrailingReturnType.isUsable() ||
+                                  TrailingReturnType.isInvalid();
+  I.Fun.TrailingReturnType      = TrailingReturnType.get();
 
   // new[] an argument array if needed.
   if (NumArgs) {
index 9ad8c3050570298e2bbf3a282f02dcc934e9add0..924b0f73d673ea38d26b72d0aa9f9d1d0dd7dce1 100644 (file)
@@ -5158,7 +5158,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
       QualType T = R->getAs<FunctionType>()->getResultType();
       DeclaratorChunk &C = D.getTypeObject(0);
       if (!T->isVoidType() && C.Fun.NumArgs == 0 && !C.Fun.isVariadic &&
-          !C.Fun.TrailingReturnType &&
+          !C.Fun.hasTrailingReturnType() &&
           C.Fun.getExceptionSpecType() == EST_None) {
         SourceRange ParenRange(C.Loc, C.EndLoc);
         Diag(C.Loc, diag::warn_empty_parens_are_function_decl) << ParenRange;
index 209c020fffd416cfed3a98f4b233906d22adfd14..21af5f4f2e8598a928dcb0e64722a400e4278c99 100644 (file)
@@ -1901,7 +1901,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
         DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
         if (DeclType.Kind == DeclaratorChunk::Function) {
           const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
-          if (FTI.TrailingReturnType) {
+          if (FTI.hasTrailingReturnType()) {
             Error = -1;
             break;
           }
@@ -2176,12 +2176,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
         // trailing-return-type is only required if we're declaring a function,
         // and not, for instance, a pointer to a function.
         if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
-            !FTI.TrailingReturnType && chunkIndex == 0) {
+            !FTI.hasTrailingReturnType() && chunkIndex == 0) {
           S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
                diag::err_auto_missing_trailing_return);
           T = Context.IntTy;
           D.setInvalidType(true);
-        } else if (FTI.TrailingReturnType) {
+        } else if (FTI.hasTrailingReturnType()) {
           // T must be exactly 'auto' at this point. See CWG issue 681.
           if (isa<ParenType>(T)) {
             S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
@@ -2195,10 +2195,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
               << T << D.getDeclSpec().getSourceRange();
             D.setInvalidType(true);
           }
-
-          T = S.GetTypeFromParser(
-            ParsedType::getFromOpaquePtr(FTI.TrailingReturnType),
-            &TInfo);
+          T = S.GetTypeFromParser(FTI.getTrailingReturnType(), &TInfo);
+          if (T.isNull()) {
+            // An error occurred parsing the trailing return type.
+            T = Context.IntTy;
+            D.setInvalidType(true);
+          }
         }
       }
 
@@ -2301,7 +2303,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
 
         FunctionProtoType::ExtProtoInfo EPI;
         EPI.Variadic = FTI.isVariadic;
-        EPI.HasTrailingReturn = FTI.TrailingReturnType;
+        EPI.HasTrailingReturn = FTI.hasTrailingReturnType();
         EPI.TypeQuals = FTI.TypeQuals;
         EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None
                     : FTI.RefQualifierIsLValueRef? RQ_LValue
@@ -3119,7 +3121,7 @@ namespace {
       assert(Chunk.Kind == DeclaratorChunk::Function);
       TL.setLocalRangeBegin(Chunk.Loc);
       TL.setLocalRangeEnd(Chunk.EndLoc);
-      TL.setTrailingReturn(!!Chunk.Fun.TrailingReturnType);
+      TL.setTrailingReturn(Chunk.Fun.hasTrailingReturnType());
 
       const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
       for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {
index 71f57dcc66e7be1e8d2e8fbe444a7fcd4e08d007..7499829185ebfe55ee106646a81f4ecf98dd8848 100644 (file)
@@ -64,5 +64,4 @@ template<typename T = auto> struct G { }; // expected-error{{'auto' not allowed
 
 using A = auto; // expected-error{{'auto' not allowed in type alias}}
 
-// FIXME: don't issue the second diagnostic for this error.
-auto k() -> auto; // expected-error{{'auto' not allowed in function return type}} unexpected-error{{without trailing return type}}
+auto k() -> auto; // expected-error{{'auto' not allowed in function return type}}
index 680e9124cb24c79f4b0a2fec079c43d9abf4d8c7..719aeeddebcc02ddce7a3d3dfd2cece61e0d58f3 100644 (file)
@@ -4,4 +4,4 @@
 // will necessarily be ill-formed as a trailing return type for a function
 // definition), and recover with a "type cannot be defined in a trailing return
 // type" error.
-auto j() -> enum { e3 }; // expected-error{{unnamed enumeration must be a definition}} expected-error {{expected a type}} expected-error {{without trailing return type}}
+auto j() -> enum { e3 }; // expected-error{{unnamed enumeration must be a definition}} expected-error {{expected a type}}
index 212ffb407b995523cc1910e4c5bb94acdff853d5..c66462a84f01603487cc966a2f40712e7895fdba 100644 (file)
@@ -21,7 +21,4 @@ void f() {
 
 // And for trailing-type-specifier-seq
 
-// FIXME: Don't treat an ill-formed trailing-return-type the same as no
-//        trailing-return-type, and avoid the second diagnostic.
-auto f() -> unknown; // expected-error{{unknown type name 'unknown'}} \
-                        expected-error{{'auto' return without trailing return type}}
+auto f() -> unknown; // expected-error{{unknown type name 'unknown'}}