]> granicus.if.org Git - clang/commitdiff
Detect operator-> chains of arbitrary length. Use a terrible data structure
authorJohn McCall <rjmccall@apple.com>
Wed, 30 Sep 2009 01:01:30 +0000 (01:01 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 30 Sep 2009 01:01:30 +0000 (01:01 +0000)
to strike fear into the hearts of CPUs everywhere.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83133 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExprCXX.cpp
test/SemaCXX/overloaded-operator.cpp

index fc32c3b3a6ff8a1f80267e2c08a09bcabcd7ffd8..25a6591d76bfa11d92949373b4e3feb1bdcda529 100644 (file)
@@ -1977,17 +1977,23 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
   //   [...] When operator->returns, the operator-> is applied  to the value
   //   returned, with the original second operand.
   if (OpKind == tok::arrow) {
+    // The set of types we've considered so far.
+    llvm::SmallVector<CanQualType,8> CTypes;
+    CTypes.push_back(Context.getCanonicalType(BaseType));
+    
     while (BaseType->isRecordType()) {
       Base = BuildOverloadedArrowExpr(S, move(Base), BaseExpr->getExprLoc());
       BaseExpr = (Expr*)Base.get();
       if (BaseExpr == NULL)
         return ExprError();
-      if (Context.getCanonicalType(BaseExpr->getType()) == 
-          Context.getCanonicalType(BaseType)) {
+      BaseType = BaseExpr->getType();
+      CanQualType CBaseType = Context.getCanonicalType(BaseType);
+      if (std::find(CTypes.begin(), CTypes.end(), CBaseType) != CTypes.end()) {
+        // TODO: note the chain of conversions
         Diag(OpLoc, diag::err_operator_arrow_circular);
         return ExprError();
       }
-      BaseType = BaseExpr->getType();
+      CTypes.push_back(CBaseType);
     }
   }
 
index c849a145e2c4851e0ba203e08f61d2d249c6c572..31da58dfcd4d479a603ff84a2575995604f4d340 100644 (file)
@@ -224,3 +224,19 @@ void m() {
   AX a; 
   a->b = 0; // expected-error {{circular pointer delegation detected}}
 }
+
+struct CircA {
+  struct CircB& operator->();
+  int val;
+};
+struct CircB {
+  struct CircC& operator->();
+};
+struct CircC {
+  struct CircA& operator->();
+};
+
+void circ() {
+  CircA a;
+  a->val = 0; // expected-error {{circular pointer delegation detected}}
+}