[cfe-commits] r85524 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaOverload.cpp lib/Sema/TreeTransform.h test/SemaTemplate/instantiate-subscript.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Thu Oct 29 13:17:02 PDT 2009
Author: cornedbee
Date: Thu Oct 29 15:17:01 2009
New Revision: 85524
URL: http://llvm.org/viewvc/llvm-project?rev=85524&view=rev
Log:
Properly instantiate usage of overloaded operator []. Fixes PR5345.
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/SemaTemplate/instantiate-subscript.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=85524&r1=85523&r2=85524&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Oct 29 15:17:01 2009
@@ -962,6 +962,10 @@
FunctionSet &Functions,
Expr *LHS, Expr *RHS);
+ OwningExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+ SourceLocation RLoc,
+ ExprArg Base,ExprArg Idx);
+
ExprResult
BuildCallToMemberFunction(Scope *S, Expr *MemExpr,
SourceLocation LParenLoc, Expr **Args,
@@ -1684,6 +1688,10 @@
SourceLocation LLoc,
ExprArg Idx,
SourceLocation RLoc);
+ OwningExprResult CreateBuiltinArraySubscriptExpr(ExprArg Base,
+ SourceLocation LLoc,
+ ExprArg Idx,
+ SourceLocation RLoc);
OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base,
SourceLocation OpLoc,
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=85524&r1=85523&r2=85524&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Oct 29 15:17:01 2009
@@ -1600,103 +1600,18 @@
LHSExp->getType()->isEnumeralType() ||
RHSExp->getType()->isRecordType() ||
RHSExp->getType()->isEnumeralType())) {
- // Add the appropriate overloaded operators (C++ [over.match.oper])
- // to the candidate set.
- OverloadCandidateSet CandidateSet;
- Expr *Args[2] = { LHSExp, RHSExp };
- AddOperatorCandidates(OO_Subscript, S, LLoc, Args, 2, CandidateSet,
- SourceRange(LLoc, RLoc));
-
- // Perform overload resolution.
- OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, LLoc, Best)) {
- case OR_Success: {
- // We found a built-in operator or an overloaded operator.
- FunctionDecl *FnDecl = Best->Function;
-
- if (FnDecl) {
- // We matched an overloaded operator. Build a call to that
- // operator.
-
- // Convert the arguments.
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
- if (PerformObjectArgumentInitialization(LHSExp, Method) ||
- PerformCopyInitialization(RHSExp,
- FnDecl->getParamDecl(0)->getType(),
- "passing"))
- return ExprError();
- } else {
- // Convert the arguments.
- if (PerformCopyInitialization(LHSExp,
- FnDecl->getParamDecl(0)->getType(),
- "passing") ||
- PerformCopyInitialization(RHSExp,
- FnDecl->getParamDecl(1)->getType(),
- "passing"))
- return ExprError();
- }
-
- // Determine the result type
- QualType ResultTy = FnDecl->getResultType().getNonReferenceType();
-
- // Build the actual expression node.
- Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
- SourceLocation());
- UsualUnaryConversions(FnExpr);
-
- Base.release();
- Idx.release();
- Args[0] = LHSExp;
- Args[1] = RHSExp;
-
- ExprOwningPtr<CXXOperatorCallExpr>
- TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
- FnExpr, Args, 2,
- ResultTy, RLoc));
- if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall.get(),
- FnDecl))
- return ExprError();
-
- return Owned(TheCall.release());
- } else {
- // We matched a built-in operator. Convert the arguments, then
- // break out so that we will build the appropriate built-in
- // operator node.
- if (PerformCopyInitialization(LHSExp, Best->BuiltinTypes.ParamTypes[0],
- "passing") ||
- PerformCopyInitialization(RHSExp, Best->BuiltinTypes.ParamTypes[1],
- "passing"))
- return ExprError();
-
- break;
- }
- }
-
- case OR_No_Viable_Function:
- // No viable function; fall through to handling this as a
- // built-in operator, which will produce an error message for us.
- break;
+ return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, move(Base),move(Idx));
+ }
- case OR_Ambiguous:
- Diag(LLoc, diag::err_ovl_ambiguous_oper)
- << "[]"
- << LHSExp->getSourceRange() << RHSExp->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
- return ExprError();
+ return CreateBuiltinArraySubscriptExpr(move(Base), LLoc, move(Idx), RLoc);
+}
- case OR_Deleted:
- Diag(LLoc, diag::err_ovl_deleted_oper)
- << Best->Function->isDeleted()
- << "[]"
- << LHSExp->getSourceRange() << RHSExp->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
- return ExprError();
- }
- // Either we found no viable overloaded operator or we matched a
- // built-in operator. In either case, fall through to trying to
- // build a built-in operation.
- }
+Action::OwningExprResult
+Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc,
+ ExprArg Idx, SourceLocation RLoc) {
+ Expr *LHSExp = static_cast<Expr*>(Base.get());
+ Expr *RHSExp = static_cast<Expr*>(Idx.get());
// Perform default conversions.
DefaultFunctionArrayConversion(LHSExp);
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=85524&r1=85523&r2=85524&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Oct 29 15:17:01 2009
@@ -4942,6 +4942,134 @@
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
}
+Action::OwningExprResult
+Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+ SourceLocation RLoc,
+ ExprArg Base, ExprArg Idx) {
+ Expr *Args[2] = { static_cast<Expr*>(Base.get()),
+ static_cast<Expr*>(Idx.get()) };
+ DeclarationName OpName =
+ Context.DeclarationNames.getCXXOperatorName(OO_Subscript);
+
+ // If either side is type-dependent, create an appropriate dependent
+ // expression.
+ if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
+
+ OverloadedFunctionDecl *Overloads
+ = OverloadedFunctionDecl::Create(Context, CurContext, OpName);
+
+ DeclRefExpr *Fn = new (Context) DeclRefExpr(Overloads, Context.OverloadTy,
+ LLoc, false, false);
+
+ Base.release();
+ Idx.release();
+ return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn,
+ Args, 2,
+ Context.DependentTy,
+ RLoc));
+ }
+
+ // Build an empty overload set.
+ OverloadCandidateSet CandidateSet;
+
+ // Subscript can only be overloaded as a member function.
+
+ // Add operator candidates that are member functions.
+ AddMemberOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet);
+
+ // Add builtin operator candidates.
+ AddBuiltinOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet);
+
+ // Perform overload resolution.
+ OverloadCandidateSet::iterator Best;
+ switch (BestViableFunction(CandidateSet, LLoc, Best)) {
+ case OR_Success: {
+ // We found a built-in operator or an overloaded operator.
+ FunctionDecl *FnDecl = Best->Function;
+
+ if (FnDecl) {
+ // We matched an overloaded operator. Build a call to that
+ // operator.
+
+ // Convert the arguments.
+ CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
+ if (PerformObjectArgumentInitialization(Args[0], Method) ||
+ PerformCopyInitialization(Args[1],
+ FnDecl->getParamDecl(0)->getType(),
+ "passing"))
+ return ExprError();
+
+ // Determine the result type
+ QualType ResultTy
+ = FnDecl->getType()->getAs<FunctionType>()->getResultType();
+ ResultTy = ResultTy.getNonReferenceType();
+
+ // Build the actual expression node.
+ Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
+ LLoc);
+ UsualUnaryConversions(FnExpr);
+
+ Base.release();
+ Idx.release();
+ ExprOwningPtr<CXXOperatorCallExpr>
+ TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
+ FnExpr, Args, 2,
+ ResultTy, RLoc));
+
+ if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall.get(),
+ FnDecl))
+ return ExprError();
+
+ return MaybeBindToTemporary(TheCall.release());
+ } else {
+ // We matched a built-in operator. Convert the arguments, then
+ // break out so that we will build the appropriate built-in
+ // operator node.
+ if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
+ Best->Conversions[0], "passing") ||
+ PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
+ Best->Conversions[1], "passing"))
+ return ExprError();
+
+ break;
+ }
+ }
+
+ case OR_No_Viable_Function: {
+ // No viable function; try to create a built-in operation, which will
+ // produce an error. Then, show the non-viable candidates.
+ OwningExprResult Result =
+ CreateBuiltinArraySubscriptExpr(move(Base), LLoc, move(Idx), RLoc);
+ assert(Result.isInvalid() &&
+ "C++ subscript operator overloading is missing candidates!");
+ if (Result.isInvalid())
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false,
+ "[]", LLoc);
+ return move(Result);
+ }
+
+ case OR_Ambiguous:
+ Diag(LLoc, diag::err_ovl_ambiguous_oper)
+ << "[]" << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true,
+ "[]", LLoc);
+ return ExprError();
+
+ case OR_Deleted:
+ Diag(LLoc, diag::err_ovl_deleted_oper)
+ << Best->Function->isDeleted() << "[]"
+ << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+ return ExprError();
+ }
+
+ // We matched a built-in operator; build it.
+ Base.release();
+ Idx.release();
+ return CreateBuiltinArraySubscriptExpr(Owned(Args[0]), LLoc,
+ Owned(Args[1]), RLoc);
+}
+
/// BuildCallToMemberFunction - Build a call to a member
/// function. MemExpr is the expression that refers to the member
/// function (and includes the object parameter), Args/NumArgs are the
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=85524&r1=85523&r2=85524&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Oct 29 15:17:01 2009
@@ -5188,10 +5188,18 @@
ExprArg Second) {
Expr *FirstExpr = (Expr *)First.get();
Expr *SecondExpr = (Expr *)Second.get();
+ DeclRefExpr *DRE
+ = cast<DeclRefExpr>(((Expr *)Callee.get())->IgnoreParenCasts());
bool isPostIncDec = SecondExpr && (Op == OO_PlusPlus || Op == OO_MinusMinus);
// Determine whether this should be a builtin operation.
- if (SecondExpr == 0 || isPostIncDec) {
+ if (Op == OO_Subscript) {
+ if (!FirstExpr->getType()->isOverloadableType() &&
+ !SecondExpr->getType()->isOverloadableType())
+ return getSema().CreateBuiltinArraySubscriptExpr(move(First),
+ DRE->getLocStart(),
+ move(Second), OpLoc);
+ } else if (SecondExpr == 0 || isPostIncDec) {
if (!FirstExpr->getType()->isOverloadableType()) {
// The argument is not of overloadable type, so try to create a
// built-in unary operation.
@@ -5221,9 +5229,6 @@
// used during overload resolution.
Sema::FunctionSet Functions;
- DeclRefExpr *DRE
- = cast<DeclRefExpr>(((Expr *)Callee.get())->IgnoreParenCasts());
-
// FIXME: Do we have to check
// IsAcceptableNonMemberOperatorCandidate for each of these?
for (OverloadIterator F(DRE->getDecl()), FEnd; F != FEnd; ++F)
@@ -5244,6 +5249,10 @@
return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(First));
}
+ if (Op == OO_Subscript)
+ return SemaRef.CreateOverloadedArraySubscriptExpr(DRE->getLocStart(), OpLoc,
+ move(First),move(Second));
+
// Create the overloaded operator invocation for binary operators.
BinaryOperator::Opcode Opc =
BinaryOperator::getOverloadedOpcode(Op);
Modified: cfe/trunk/test/SemaTemplate/instantiate-subscript.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-subscript.cpp?rev=85524&r1=85523&r2=85524&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-subscript.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-subscript.cpp Thu Oct 29 15:17:01 2009
@@ -6,7 +6,7 @@
};
struct Sub1 {
- long &operator[](long);
+ long &operator[](long); // expected-note{{candidate function}}
};
struct ConvertibleToInt {
@@ -24,3 +24,18 @@
template struct Subscript0<Sub0, int, int&>;
template struct Subscript0<Sub1, ConvertibleToInt, long&>;
template struct Subscript0<Sub1, Sub0, long&>; // expected-note{{instantiation}}
+
+// PR5345
+template <typename T>
+struct S {
+ bool operator[](int n) const { return true; }
+};
+
+template <typename T>
+void Foo(const S<int>& s, T x) {
+ if (s[0]) {}
+}
+
+void Bar() {
+ Foo(S<int>(), 0);
+}
More information about the cfe-commits
mailing list