[cfe-commits] r72498 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Type.h lib/AST/ASTContext.cpp lib/AST/Type.cpp lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaType.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Wed May 27 15:11:53 PDT 2009


Author: cornedbee
Date: Wed May 27 17:11:52 2009
New Revision: 72498

URL: http://llvm.org/viewvc/llvm-project?rev=72498&view=rev
Log:
Reintroduce the home for exception specs, and make Sema fill it. However, keep the spec out of the canonical type this time. Net effect is currently nothing, because the spec isn't checked anywhere.

Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaType.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=72498&r1=72497&r2=72498&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Wed May 27 17:11:52 2009
@@ -287,12 +287,14 @@
   /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
   ///
   QualType getFunctionNoProtoType(QualType ResultTy);
-  
+
   /// getFunctionType - Return a normal function type with a typed argument
   /// list.  isVariadic indicates whether the argument list includes '...'.
   QualType getFunctionType(QualType ResultTy, const QualType *ArgArray,
                            unsigned NumArgs, bool isVariadic,
-                           unsigned TypeQuals);
+                           unsigned TypeQuals, bool hasExceptionSpec = false,
+                           bool hasAnyExceptionSpec = false,
+                           unsigned NumExs = 0, const QualType *ExArray = 0);
 
   /// getTypeDeclType - Return the unique reference to the type for
   /// the specified type declaration.

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=72498&r1=72497&r2=72498&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed May 27 17:11:52 2009
@@ -1151,7 +1151,9 @@
 
 /// FunctionProtoType - Represents a prototype with argument type info, e.g.
 /// 'int foo(int)' or 'int foo(void)'.  'void' is represented as having no
-/// arguments, not as having a single void argument.
+/// arguments, not as having a single void argument. Such a type can have an
+/// exception specification, but this specification is not part of the canonical
+/// type.
 class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
   /// hasAnyDependentType - Determine whether there are any dependent
   /// types within the arguments passed in.
@@ -1164,23 +1166,42 @@
   }
 
   FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned numArgs,
-                    bool isVariadic, unsigned typeQuals, QualType Canonical)
+                    bool isVariadic, unsigned typeQuals, bool hasExs,
+                    bool hasAnyExs, const QualType *ExArray,
+                    unsigned numExs, QualType Canonical)
     : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical,
                    (Result->isDependentType() || 
                     hasAnyDependentType(ArgArray, numArgs))),
-      NumArgs(numArgs) {
+      NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),
+      AnyExceptionSpec(hasAnyExs) {
     // Fill in the trailing argument array.
-    QualType *ArgInfo = reinterpret_cast<QualType *>(this+1);;
+    QualType *ArgInfo = reinterpret_cast<QualType*>(this+1);
     for (unsigned i = 0; i != numArgs; ++i)
       ArgInfo[i] = ArgArray[i];
+    // Fill in the exception array.
+    QualType *Ex = ArgInfo + numArgs;
+    for (unsigned i = 0; i != numExs; ++i)
+      Ex[i] = ExArray[i];
   }
-  
+
   /// NumArgs - The number of arguments this function has, not counting '...'.
-  unsigned NumArgs;
-  
+  unsigned NumArgs : 20;
+
+  /// NumExceptions - The number of types in the exception spec, if any.
+  unsigned NumExceptions : 10;
+
+  /// HasExceptionSpec - Whether this function has an exception spec at all.
+  bool HasExceptionSpec : 1;
+
+  /// AnyExceptionSpec - Whether this function has a throw(...) spec.
+  bool AnyExceptionSpec : 1;
+
   /// ArgInfo - There is an variable size array after the class in memory that
   /// holds the argument types.
-  
+
+  /// Exceptions - There is another variable size array after ArgInfo that
+  /// holds the exception types.
+
   friend class ASTContext;  // ASTContext creates these.
 
 public:
@@ -1189,7 +1210,15 @@
     assert(i < NumArgs && "Invalid argument number!");
     return arg_type_begin()[i];
   }
-    
+
+  bool hasExceptionSpec() const { return HasExceptionSpec; }
+  bool hasAnyExceptionSpec() const { return AnyExceptionSpec; }
+  unsigned getNumExceptions() const { return NumExceptions; }
+  QualType getExceptionType(unsigned i) const {
+    assert(i < NumExceptions && "Invalid exception number!");
+    return exception_begin()[i];
+  }
+
   bool isVariadic() const { return getSubClassData(); }
   unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
   
@@ -1198,18 +1227,29 @@
     return reinterpret_cast<const QualType *>(this+1);
   }
   arg_type_iterator arg_type_end() const { return arg_type_begin()+NumArgs; }
-  
+
+  typedef const QualType *exception_iterator;
+  exception_iterator exception_begin() const {
+    // exceptions begin where arguments end
+    return arg_type_end();
+  }
+  exception_iterator exception_end() const {
+    return exception_begin() + NumExceptions;
+  }
+
   virtual void getAsStringInternal(std::string &InnerString) const;
 
   static bool classof(const Type *T) {
     return T->getTypeClass() == FunctionProto;
   }
   static bool classof(const FunctionProtoType *) { return true; }
-  
+
   void Profile(llvm::FoldingSetNodeID &ID);
   static void Profile(llvm::FoldingSetNodeID &ID, QualType Result,
                       arg_type_iterator ArgTys, unsigned NumArgs,
-                      bool isVariadic, unsigned TypeQuals);
+                      bool isVariadic, unsigned TypeQuals,
+                      bool hasExceptionSpec, bool anyExceptionSpec,
+                      unsigned NumExceptions, exception_iterator Exs);
 };
 
 

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=72498&r1=72497&r2=72498&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed May 27 17:11:52 2009
@@ -1261,49 +1261,58 @@
 /// list.  isVariadic indicates whether the argument list includes '...'.
 QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
                                      unsigned NumArgs, bool isVariadic,
-                                     unsigned TypeQuals) {
+                                     unsigned TypeQuals, bool hasExceptionSpec,
+                                     bool hasAnyExceptionSpec, unsigned NumExs,
+                                     const QualType *ExArray) {
   // Unique functions, to guarantee there is only one function of a particular
   // structure.
   llvm::FoldingSetNodeID ID;
   FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic,
-                             TypeQuals);
+                             TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
+                             NumExs, ExArray);
 
   void *InsertPos = 0;
   if (FunctionProtoType *FTP = 
         FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos))
     return QualType(FTP, 0);
-    
-  // Determine whether the type being created is already canonical or not.  
+
+  // Determine whether the type being created is already canonical or not.
   bool isCanonical = ResultTy->isCanonical();
+  if (hasExceptionSpec)
+    isCanonical = false;
   for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
     if (!ArgArray[i]->isCanonical())
       isCanonical = false;
 
   // If this type isn't canonical, get the canonical version of it.
+  // The exception spec is not part of the canonical type.
   QualType Canonical;
   if (!isCanonical) {
     llvm::SmallVector<QualType, 16> CanonicalArgs;
     CanonicalArgs.reserve(NumArgs);
     for (unsigned i = 0; i != NumArgs; ++i)
       CanonicalArgs.push_back(getCanonicalType(ArgArray[i]));
-    
+
     Canonical = getFunctionType(getCanonicalType(ResultTy),
                                 CanonicalArgs.data(), NumArgs,
                                 isVariadic, TypeQuals);
-    
+
     // Get the new insert position for the node we care about.
     FunctionProtoType *NewIP =
       FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos);
     assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
   }
-  
+
   // FunctionProtoType objects are allocated with extra bytes after them
-  // for a variable size array (for parameter types) at the end of them.
+  // for two variable size arrays (for parameter and exception types) at the
+  // end of them.
   FunctionProtoType *FTP = 
-    (FunctionProtoType*)Allocate(sizeof(FunctionProtoType) + 
-                                 NumArgs*sizeof(QualType), 8);
+    (FunctionProtoType*)Allocate(sizeof(FunctionProtoType) +
+                                 NumArgs*sizeof(QualType) +
+                                 NumExs*sizeof(QualType), 8);
   new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, isVariadic,
-                              TypeQuals, Canonical);
+                              TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
+                              ExArray, NumExs, Canonical);
   Types.push_back(FTP);
   FunctionProtoTypes.InsertNode(FTP, InsertPos);
   return QualType(FTP, 0);
@@ -2912,6 +2921,8 @@
     allRTypes = false;
 
   if (lproto && rproto) { // two C99 style function prototypes
+    assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() &&
+           "C++ shouldn't be here");
     unsigned lproto_nargs = lproto->getNumArgs();
     unsigned rproto_nargs = rproto->getNumArgs();
 
@@ -2950,6 +2961,7 @@
 
   const FunctionProtoType *proto = lproto ? lproto : rproto;
   if (proto) {
+    assert(!proto->hasExceptionSpec() && "C++ shouldn't be here");
     if (proto->isVariadic()) return QualType();
     // Check that the types are compatible with the types that
     // would result from default argument promotions (C99 6.7.5.3p15).

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=72498&r1=72497&r2=72498&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed May 27 17:11:52 2009
@@ -927,17 +927,26 @@
 void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
                                 arg_type_iterator ArgTys,
                                 unsigned NumArgs, bool isVariadic,
-                                unsigned TypeQuals) {
+                                unsigned TypeQuals, bool hasExceptionSpec,
+                                bool anyExceptionSpec, unsigned NumExceptions,
+                                exception_iterator Exs) {
   ID.AddPointer(Result.getAsOpaquePtr());
   for (unsigned i = 0; i != NumArgs; ++i)
     ID.AddPointer(ArgTys[i].getAsOpaquePtr());
   ID.AddInteger(isVariadic);
   ID.AddInteger(TypeQuals);
+  ID.AddInteger(hasExceptionSpec);
+  if (hasExceptionSpec) {
+    ID.AddInteger(anyExceptionSpec);
+    for(unsigned i = 0; i != NumExceptions; ++i)
+      ID.AddPointer(Exs[i].getAsOpaquePtr());
+  }
 }
 
 void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) {
   Profile(ID, getResultType(), arg_type_begin(), NumArgs, isVariadic(),
-          getTypeQuals());
+          getTypeQuals(), hasExceptionSpec(), hasAnyExceptionSpec(),
+          getNumExceptions(), exception_begin());
 }
 
 void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID,

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=72498&r1=72497&r2=72498&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Wed May 27 17:11:52 2009
@@ -1670,8 +1670,16 @@
       ParamTypes.push_back(GetType(Record[Idx++]));
     bool isVariadic = Record[Idx++];
     unsigned Quals = Record[Idx++];
+    bool hasExceptionSpec = Record[Idx++];
+    bool hasAnyExceptionSpec = Record[Idx++];
+    unsigned NumExceptions = Record[Idx++];
+    llvm::SmallVector<QualType, 2> Exceptions;
+    for (unsigned I = 0; I != NumExceptions; ++I)
+      Exceptions.push_back(GetType(Record[Idx++]));
     return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams,
-                                    isVariadic, Quals);
+                                    isVariadic, Quals, hasExceptionSpec,
+                                    hasAnyExceptionSpec, NumExceptions,
+                                    Exceptions.data());
   }
 
   case pch::TYPE_TYPEDEF:

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=72498&r1=72497&r2=72498&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Wed May 27 17:11:52 2009
@@ -162,6 +162,11 @@
     Writer.AddTypeRef(T->getArgType(I), Record);
   Record.push_back(T->isVariadic());
   Record.push_back(T->getTypeQuals());
+  Record.push_back(T->hasExceptionSpec());
+  Record.push_back(T->hasAnyExceptionSpec());
+  Record.push_back(T->getNumExceptions());
+  for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I)
+    Writer.AddTypeRef(T->getExceptionType(I), Record);
   Code = pch::TYPE_FUNCTION_PROTO;
 }
 

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=72498&r1=72497&r2=72498&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed May 27 17:11:52 2009
@@ -729,6 +729,7 @@
         (OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) {
       // The old declaration provided a function prototype, but the
       // new declaration does not. Merge in the prototype.
+      assert(!OldProto->hasExceptionSpec() && "Exception spec in C");
       llvm::SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(),
                                                  OldProto->arg_type_end());
       NewQType = Context.getFunctionType(NewFuncType->getResultType(),

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=72498&r1=72497&r2=72498&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed May 27 17:11:52 2009
@@ -999,6 +999,9 @@
   QualType ClassType = Context.getTypeDeclType(ClassDecl);
   ClassType = Context.getCanonicalType(ClassType);
 
+  // FIXME: Implicit declarations have exception specifications, which are
+  // the union of the specifications of the implicitly called functions.
+
   if (!ClassDecl->hasUserDeclaredConstructor()) {
     // C++ [class.ctor]p5:
     //   A default constructor for a class X is a constructor of class X

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=72498&r1=72497&r2=72498&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed May 27 17:11:52 2009
@@ -716,12 +716,20 @@
         T = Context.IntTy;
         D.setInvalidType(true);
       }
-        
+
       if (FTI.NumArgs == 0) {
         if (getLangOptions().CPlusPlus) {
           // C++ 8.3.5p2: If the parameter-declaration-clause is empty, the
           // function takes no arguments.
-          T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic,FTI.TypeQuals);
+          llvm::SmallVector<QualType, 4> Exceptions;
+          Exceptions.reserve(FTI.NumExceptions);
+          for(unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei)
+            Exceptions.push_back(
+              QualType::getFromOpaquePtr(FTI.Exceptions[ei]));
+          T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic, FTI.TypeQuals,
+                                      FTI.hasExceptionSpec,
+                                      FTI.hasAnyExceptionSpec,
+                                      FTI.NumExceptions, Exceptions.data());
         } else if (FTI.isVariadic) {
           // We allow a zero-parameter variadic function in C if the
           // function is marked with the "overloadable"
@@ -795,8 +803,17 @@
           
           ArgTys.push_back(ArgTy);
         }
+
+        llvm::SmallVector<QualType, 4> Exceptions;
+        Exceptions.reserve(FTI.NumExceptions);
+        for(unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei)
+          Exceptions.push_back(QualType::getFromOpaquePtr(FTI.Exceptions[ei]));
+
         T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(),
-                                    FTI.isVariadic, FTI.TypeQuals);
+                                    FTI.isVariadic, FTI.TypeQuals,
+                                    FTI.hasExceptionSpec,
+                                    FTI.hasAnyExceptionSpec,
+                                    FTI.NumExceptions, Exceptions.data());
       }
       break;
     }





More information about the cfe-commits mailing list