aaron.ballman created this revision.
aaron.ballman added a reviewer: rsmith.
aaron.ballman added subscribers: cfe-commits, hintonda, alexfh.

We do not currently track the source locations for exception specifications 
such that their source range can be queried through the AST. This leads to 
trying to write more complex code to determine the source range for uses like 
FixItHints (see D18575 for an example). In addition to use within tools like 
clang-tidy, I think this information may become more important to track as 
exception specifications become more integrated into the type system.

One thing this patch is missing is a test case. I'm not certain of the best way 
to test this functionality in isolation; suggestions welcome.

http://reviews.llvm.org/D20428

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

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/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