]> granicus.if.org Git - clang/commitdiff
Check dynamic_cast is not used with -fno-rtti, unless it is a noop or can be resolved...
authorArnaud A. de Grandmaison <arnaud.adegm@gmail.com>
Thu, 1 Aug 2013 08:28:32 +0000 (08:28 +0000)
committerArnaud A. de Grandmaison <arnaud.adegm@gmail.com>
Thu, 1 Aug 2013 08:28:32 +0000 (08:28 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187564 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaCast.cpp
test/CodeGenCXX/dynamic_cast-no-rtti.cpp [new file with mode: 0644]
test/SemaCXX/no-rtti.cpp

index f6a3515d7f57605f6799f7a8142cb69e1918298c..6438008a1e4f206e86f36181b91c5de4d4ed7465 100644 (file)
@@ -5036,6 +5036,8 @@ def err_not_tag_in_scope : Error<
 
 def err_no_typeid_with_fno_rtti : Error<
   "cannot use typeid with -fno-rtti">;
+def err_no_dynamic_cast_with_fno_rtti : Error<
+  "cannot use dynamic_cast with -fno-rtti">;
 
 def err_cannot_form_pointer_to_member_of_reference_type : Error<
   "cannot form a pointer-to-member to member %0 of reference type %1">;
index 1adb037f0e997ca96ee665d11fafaebe627b0497..888c14ec3924241782ef59b53ff6e9ad0fbd2539 100644 (file)
@@ -667,6 +667,13 @@ void CastOperation::CheckDynamicCast() {
   Self.MarkVTableUsed(OpRange.getBegin(), 
                       cast<CXXRecordDecl>(SrcRecord->getDecl()));
 
+  // dynamic_cast is not available with fno-rtti
+  if (!Self.getLangOpts().RTTI) {
+    Self.Diag(OpRange.getBegin(), diag::err_no_dynamic_cast_with_fno_rtti);
+    SrcExpr = ExprError();
+    return;
+  }
+
   // Done. Everything else is run-time checks.
   Kind = CK_Dynamic;
 }
diff --git a/test/CodeGenCXX/dynamic_cast-no-rtti.cpp b/test/CodeGenCXX/dynamic_cast-no-rtti.cpp
new file mode 100644 (file)
index 0000000..2060e1d
--- /dev/null
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -emit-llvm %s -verify -fno-rtti -o - | FileCheck %s
+// expected-no-diagnostics
+
+struct A {
+  virtual ~A(){};
+};
+
+struct B : public A {
+  B() : A() {}
+};
+
+// An upcast can be resolved statically and can be used with -fno-rtti, iff it
+// does not use runtime support.
+A *upcast(B *b) {
+  return dynamic_cast<A *>(b);
+// CHECK: define %struct.A* @_Z6upcastP1B
+// CHECK-NOT: call i8* @__dynamic_cast
+}
+
+// A NoOp dynamic_cast can be used with -fno-rtti iff it does not use
+// runtime support.
+B *samecast(B *b) {
+  return dynamic_cast<B *>(b);
+// CHECK: define %struct.B* @_Z8samecastP1B
+// CHECK-NOT: call i8* @__dynamic_cast
+}
index 75167050dca2101922f711290902a6550e208cb9..3d6e109551d4676babd5dddd0e6c5c676f2933b7 100644 (file)
@@ -8,3 +8,17 @@ void f()
 {
   (void)typeid(int); // expected-error {{cannot use typeid with -fno-rtti}}
 }
+
+namespace {
+struct A {
+  virtual ~A(){};
+};
+
+struct B : public A {
+  B() : A() {}
+};
+}
+
+bool isa_B(A *a) {
+  return dynamic_cast<B *>(a) != 0; // expected-error {{cannot use dynamic_cast with -fno-rtti}}
+}