diff options
author | John McCall <rjmccall@apple.com> | 2009-09-30 01:01:30 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-09-30 01:01:30 +0000 |
commit | c4e8321deb2bd83f734a09749460050f40ec51d1 (patch) | |
tree | ae7bd0f1949809d7b7fd95042201f8eab405ea8d | |
parent | 4a4e345a8bf749b5462a127ecfb1f90d4a9d6ba7 (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.cpp | 12 | ||||
-rw-r--r-- | test/SemaCXX/overloaded-operator.cpp | 16 |
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}} +} |