aaron.ballman updated this revision to Diff 57798.
aaron.ballman added a comment.

For noexcept specifications without an expression, now tracking the full source 
range. Also, added tests.


http://reviews.llvm.org/D20428

Files:
  include/clang/AST/Decl.h
  include/clang/AST/TypeLoc.h
  lib/AST/Decl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Sema/SemaType.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTWriter.cpp
  unittests/AST/SourceLocationTest.cpp

Index: unittests/AST/SourceLocationTest.cpp
===================================================================
--- unittests/AST/SourceLocationTest.cpp
+++ unittests/AST/SourceLocationTest.cpp
@@ -580,5 +580,44 @@
       Language::Lang_CXX11));
 }
 
+class ExceptionSpecRangeVerifier : public RangeVerifier<TypeLoc> {
+protected:
+  SourceRange getRange(const TypeLoc &Node) override {
+    auto T =
+      Node.getUnqualifiedLoc().castAs<FunctionProtoTypeLoc>();
+    assert(!T.isNull());
+    return T.getExceptionSpecRange();
+  }
+};
+
+TEST(FunctionDecl, ExceptionSpecifications) {
+  ExceptionSpecRangeVerifier Verifier;
+
+  Verifier.expectRange(1, 10, 1, 16);
+  EXPECT_TRUE(Verifier.match("void f() throw();\n", loc(functionType())));
+
+  Verifier.expectRange(1, 10, 1, 34);
+  EXPECT_TRUE(Verifier.match("void f() throw(void(void) throw());\n",
+                             loc(functionType())));
+
+  Verifier.expectRange(1, 10, 1, 19);
+  std::vector<std::string> Args;
+  Args.push_back("-fms-extensions");
+  EXPECT_TRUE(Verifier.match("void f() throw(...);\n", loc(functionType()),
+                             Args, Language::Lang_CXX));
+
+  Verifier.expectRange(1, 10, 1, 17);
+  EXPECT_TRUE(Verifier.match("void f() noexcept;\n", loc(functionType()),
+                             Language::Lang_CXX11));
+
+  Verifier.expectRange(1, 10, 1, 24);
+  EXPECT_TRUE(Verifier.match("void f() noexcept(false);\n", loc(functionType()),
+                             Language::Lang_CXX11));
+
+  Verifier.expectRange(1, 10, 1, 32);
+  EXPECT_TRUE(Verifier.match("void f() noexcept(noexcept(1+1));\n",
+                             loc(functionType()), Language::Lang_CXX11));
+}
+
 } // end namespace ast_matchers
 } // end namespace clang
Index: lib/Serialization/ASTWriter.cpp
===================================================================
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -572,6 +572,7 @@
   Record.AddSourceLocation(TL.getLocalRangeBegin());
   Record.AddSourceLocation(TL.getLParenLoc());
   Record.AddSourceLocation(TL.getRParenLoc());
+  Record.AddSourceRange(TL.getExceptionSpecRange());
   Record.AddSourceLocation(TL.getLocalRangeEnd());
   for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i)
     Record.AddDeclRef(TL.getParam(i));
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -5812,6 +5812,8 @@
   TL.setLocalRangeBegin(ReadSourceLocation(Record, Idx));
   TL.setLParenLoc(ReadSourceLocation(Record, Idx));
   TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+  TL.setExceptionSpecRange(SourceRange(ReadSourceLocation(Record, Idx),
+                                       ReadSourceLocation(Record, Idx)));
   TL.setLocalRangeEnd(ReadSourceLocation(Record, Idx));
   for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) {
     TL.setParam(i, ReadDeclAs<ParmVarDecl>(Record, Idx));
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -4919,6 +4919,7 @@
   NewTL.setLocalRangeBegin(TL.getLocalRangeBegin());
   NewTL.setLParenLoc(TL.getLParenLoc());
   NewTL.setRParenLoc(TL.getRParenLoc());
+  NewTL.setExceptionSpecRange(TL.getExceptionSpecRange());
   NewTL.setLocalRangeEnd(TL.getLocalRangeEnd());
   for (unsigned i = 0, e = NewTL.getNumParams(); i != e; ++i)
     NewTL.setParam(i, ParamDecls[i]);
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -5065,7 +5065,7 @@
         ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
         TL.setParam(tpi++, Param);
       }
-      // FIXME: exception specs
+      TL.setExceptionSpecRange(FTI.getExceptionSpecRange());
     }
     void VisitParenTypeLoc(ParenTypeLoc TL) {
       assert(Chunk.Kind == DeclaratorChunk::Paren);
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -3400,7 +3400,8 @@
 
   // If we already had a dynamic specification, parse the noexcept for,
   // recovery, but emit a diagnostic and don't store the results.
-  SourceRange NoexceptRange;
+  SourceRange NoexceptRange(Tok.getLocation(),
+                            Tok.getEndLoc().getLocWithOffset(-1));
   ExceptionSpecificationType NoexceptType = EST_None;
 
   SourceLocation KeywordLoc = ConsumeToken();
@@ -3423,7 +3424,6 @@
   } else {
     // There is no argument.
     NoexceptType = EST_BasicNoexcept;
-    NoexceptRange = SourceRange(KeywordLoc, KeywordLoc);
   }
 
   if (Result == EST_None) {
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -2935,6 +2935,18 @@
   return RTRange;
 }
 
+SourceRange FunctionDecl::getExceptionSpecSourceRange() const {
+  const TypeSourceInfo *TSI = getTypeSourceInfo();
+  if (!TSI)
+    return SourceRange();
+  FunctionTypeLoc FTL =
+    TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>();
+  if (!FTL)
+    return SourceRange();
+
+  return FTL.getExceptionSpecRange();
+}
+
 const Attr *FunctionDecl::getUnusedResultAttr() const {
   QualType RetType = getReturnType();
   if (RetType->isRecordType()) {
Index: include/clang/AST/TypeLoc.h
===================================================================
--- include/clang/AST/TypeLoc.h
+++ include/clang/AST/TypeLoc.h
@@ -1248,6 +1248,7 @@
   SourceLocation LocalRangeBegin;
   SourceLocation LParenLoc;
   SourceLocation RParenLoc;
+  SourceRange ExceptionSpecRange;
   SourceLocation LocalRangeEnd;
 };
 
@@ -1289,6 +1290,13 @@
     return SourceRange(getLParenLoc(), getRParenLoc());
   }
 
+  SourceRange getExceptionSpecRange() const {
+    return this->getLocalData()->ExceptionSpecRange;
+  }
+  void setExceptionSpecRange(SourceRange R) {
+    this->getLocalData()->ExceptionSpecRange = R;
+  }
+
   ArrayRef<ParmVarDecl *> getParams() const {
     return llvm::makeArrayRef(getParmArray(), getNumParams());
   }
@@ -1318,6 +1326,7 @@
     setLocalRangeBegin(Loc);
     setLParenLoc(Loc);
     setRParenLoc(Loc);
+    setExceptionSpecRange(SourceRange(Loc));
     setLocalRangeEnd(Loc);
     for (unsigned i = 0, e = getNumParams(); i != e; ++i)
       setParam(i, nullptr);
Index: include/clang/AST/Decl.h
===================================================================
--- include/clang/AST/Decl.h
+++ include/clang/AST/Decl.h
@@ -2019,6 +2019,10 @@
   /// limited representation in the AST.
   SourceRange getReturnTypeSourceRange() const;
 
+  /// \brief Attempt to compute an informative source range covering the
+  /// function exception specification, if any.
+  SourceRange getExceptionSpecSourceRange() const;
+
   /// \brief Determine the type of an expression that calls this function.
   QualType getCallResultType() const {
     assert(getType()->getAs<FunctionType>() && "Expected a FunctionType!");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to