aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-09-30 01:01:30 +0000
committerJohn McCall <rjmccall@apple.com>2009-09-30 01:01:30 +0000
commitc4e8321deb2bd83f734a09749460050f40ec51d1 (patch)
treeae7bd0f1949809d7b7fd95042201f8eab405ea8d
parent4a4e345a8bf749b5462a127ecfb1f90d4a9d6ba7 (diff)
Detect operator-> chains of arbitrary length. Use a terrible data structure
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
-rw-r--r--lib/Sema/SemaExprCXX.cpp12
-rw-r--r--test/SemaCXX/overloaded-operator.cpp16
2 files changed, 25 insertions, 3 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index fc32c3b3a6..25a6591d76 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -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);
}
}
diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp
index c849a145e2..31da58dfcd 100644
--- a/test/SemaCXX/overloaded-operator.cpp
+++ b/test/SemaCXX/overloaded-operator.cpp
@@ -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}}
+}