[cfe-commits] r131177 - in /cfe/trunk: lib/AST/Expr.cpp test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp

Eli Friedman eli.friedman at gmail.com
Tue May 10 22:22:44 PDT 2011


Author: efriedma
Date: Wed May 11 00:22:44 2011
New Revision: 131177

URL: http://llvm.org/viewvc/llvm-project?rev=131177&view=rev
Log:
PR9882: Fix noexcept to deal with dependent new, delete, calls, and
dynamic_cast correctly.


Modified:
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=131177&r1=131176&r2=131177&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Wed May 11 00:22:44 2011
@@ -1693,6 +1693,9 @@
   if (!DC->getTypeAsWritten()->isReferenceType())
     return Expr::CT_Cannot;
 
+  if (DC->getSubExpr()->isTypeDependent())
+    return Expr::CT_Dependent;
+
   return DC->getCastKind() == clang::CK_Dynamic? Expr::CT_Can : Expr::CT_Cannot;
 }
 
@@ -1747,7 +1750,11 @@
   case CallExprClass:
   case CXXOperatorCallExprClass:
   case CXXMemberCallExprClass: {
-    CanThrowResult CT = CanCalleeThrow(C,cast<CallExpr>(this)->getCalleeDecl());
+    CanThrowResult CT;
+    if (isTypeDependent())
+      CT = CT_Dependent;
+    else
+      CT = CanCalleeThrow(C, cast<CallExpr>(this)->getCalleeDecl());
     if (CT == CT_Can)
       return CT;
     return MergeCanThrow(CT, CanSubExprsThrow(C, this));
@@ -1763,7 +1770,11 @@
   }
 
   case CXXNewExprClass: {
-    CanThrowResult CT = MergeCanThrow(
+    CanThrowResult CT;
+    if (isTypeDependent())
+      CT = CT_Dependent;
+    else
+      CT = MergeCanThrow(
         CanCalleeThrow(C, cast<CXXNewExpr>(this)->getOperatorNew()),
         CanCalleeThrow(C, cast<CXXNewExpr>(this)->getConstructor(),
                        /*NullThrows*/false));
@@ -1773,22 +1784,18 @@
   }
 
   case CXXDeleteExprClass: {
-    CanThrowResult CT = CanCalleeThrow(C,
-        cast<CXXDeleteExpr>(this)->getOperatorDelete());
-    if (CT == CT_Can)
-      return CT;
-    const Expr *Arg = cast<CXXDeleteExpr>(this)->getArgument();
-    // Unwrap exactly one implicit cast, which converts all pointers to void*.
-    if (const ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
-      Arg = Cast->getSubExpr();
-    if (const PointerType *PT = Arg->getType()->getAs<PointerType>()) {
-      if (const RecordType *RT = PT->getPointeeType()->getAs<RecordType>()) {
-        CanThrowResult CT2 = CanCalleeThrow(C,
-            cast<CXXRecordDecl>(RT->getDecl())->getDestructor());
-        if (CT2 == CT_Can)
-          return CT2;
-        CT = MergeCanThrow(CT, CT2);
+    CanThrowResult CT;
+    QualType DTy = cast<CXXDeleteExpr>(this)->getDestroyedType();
+    if (DTy.isNull() || DTy->isDependentType()) {
+      CT = CT_Dependent;
+    } else {
+      CT = CanCalleeThrow(C, cast<CXXDeleteExpr>(this)->getOperatorDelete());
+      if (const RecordType *RT = DTy->getAs<RecordType>()) {
+        const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+        CT = MergeCanThrow(CT, CanCalleeThrow(C, RD->getDestructor()));
       }
+      if (CT == CT_Can)
+        return CT;
     }
     return MergeCanThrow(CT, CanSubExprsThrow(C, this));
   }

Modified: cfe/trunk/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp?rev=131177&r1=131176&r2=131177&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp Wed May 11 00:22:44 2011
@@ -155,12 +155,16 @@
   N(G3());
 }
 
+template <class T> void f(T&&) noexcept;
 template <typename T, bool b>
 void late() {
   B(b, typeid(*(T*)0));
   B(b, T(1));
   B(b, static_cast<T>(S2(0, 0)));
   B(b, S1() + T());
+  P(f(T()));
+  P(new (0) T);
+  P(delete (T*)0);
 }
 struct S3 {
   virtual ~S3() throw();
@@ -168,9 +172,15 @@
   explicit S3(int);
   S3(const S2&);
 };
+template <class T> T&& f2() noexcept;
+template <typename T>
+void late2() {
+  P(dynamic_cast<S3&>(f2<T&>()));
+}
 void operator +(const S1&, float) throw();
 void operator +(const S1&, const S3&);
 void tlate() {
   late<float, true>();
   late<S3, false>();
+  late2<S3>();
 }





More information about the cfe-commits mailing list