From c4e8321deb2bd83f734a09749460050f40ec51d1 Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 30 Sep 2009 01:01:30 +0000 Subject: [PATCH] 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 --- lib/Sema/SemaExprCXX.cpp | 12 +++++++++--- 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 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}} +} -- 2.40.0