forked from OSchip/llvm-project
When instantiating a UnaryOperator, allow the resulting expression to
still be dependent or invoke an overloaded operator. Previously, we only supported builtin operators. BinaryOperator/CompoundAssignOperator didn't have this issue because we always built a CXXOperatorCallExpr node, even when name lookup didn't find any functions to save until instantiation time. Now, that code builds a BinaryOperator or CompoundAssignOperator rather than a CXXOperatorCallExpr, to save some space. llvm-svn: 86087
This commit is contained in:
parent
45119d8850
commit
5287f091b2
|
@ -1667,6 +1667,8 @@ public:
|
|||
OwningExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc,
|
||||
unsigned OpcIn,
|
||||
ExprArg InputArg);
|
||||
OwningExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc,
|
||||
UnaryOperator::Opcode Opc, ExprArg input);
|
||||
virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
|
||||
tok::TokenKind Op, ExprArg Input);
|
||||
|
||||
|
@ -1792,6 +1794,9 @@ public:
|
|||
virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
|
||||
tok::TokenKind Kind,
|
||||
ExprArg LHS, ExprArg RHS);
|
||||
OwningExprResult BuildBinOp(Scope *S, SourceLocation OpLoc,
|
||||
BinaryOperator::Opcode Opc,
|
||||
Expr *lhs, Expr *rhs);
|
||||
OwningExprResult CreateBuiltinBinOp(SourceLocation TokLoc,
|
||||
unsigned Opc, Expr *lhs, Expr *rhs);
|
||||
|
||||
|
|
|
@ -5509,6 +5509,12 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
|
|||
// Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0"
|
||||
DiagnoseBinOpPrecedence(*this, Opc, TokLoc, lhs, rhs);
|
||||
|
||||
return BuildBinOp(S, TokLoc, Opc, lhs, rhs);
|
||||
}
|
||||
|
||||
Action::OwningExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
|
||||
BinaryOperator::Opcode Opc,
|
||||
Expr *lhs, Expr *rhs) {
|
||||
if (getLangOptions().CPlusPlus &&
|
||||
(lhs->getType()->isOverloadableType() ||
|
||||
rhs->getType()->isOverloadableType())) {
|
||||
|
@ -5519,21 +5525,22 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
|
|||
FunctionSet Functions;
|
||||
OverloadedOperatorKind OverOp = BinaryOperator::getOverloadedOperator(Opc);
|
||||
if (OverOp != OO_None) {
|
||||
LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(),
|
||||
Functions);
|
||||
if (S)
|
||||
LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(),
|
||||
Functions);
|
||||
Expr *Args[2] = { lhs, rhs };
|
||||
DeclarationName OpName
|
||||
= Context.DeclarationNames.getCXXOperatorName(OverOp);
|
||||
ArgumentDependentLookup(OpName, /*Operator*/true, Args, 2, Functions);
|
||||
}
|
||||
|
||||
|
||||
// Build the (potentially-overloaded, potentially-dependent)
|
||||
// binary operation.
|
||||
return CreateOverloadedBinOp(TokLoc, Opc, Functions, lhs, rhs);
|
||||
return CreateOverloadedBinOp(OpLoc, Opc, Functions, lhs, rhs);
|
||||
}
|
||||
|
||||
|
||||
// Build a built-in binary operation.
|
||||
return CreateBuiltinBinOp(TokLoc, Opc, lhs, rhs);
|
||||
return CreateBuiltinBinOp(OpLoc, Opc, lhs, rhs);
|
||||
}
|
||||
|
||||
Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
|
||||
|
@ -5624,12 +5631,10 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
|
|||
return Owned(new (Context) UnaryOperator(Input, Opc, resultType, OpLoc));
|
||||
}
|
||||
|
||||
// Unary Operators. 'Tok' is the token for the operator.
|
||||
Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
|
||||
tok::TokenKind Op, ExprArg input) {
|
||||
Action::OwningExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
|
||||
UnaryOperator::Opcode Opc,
|
||||
ExprArg input) {
|
||||
Expr *Input = (Expr*)input.get();
|
||||
UnaryOperator::Opcode Opc = ConvertTokenKindToUnaryOpcode(Op);
|
||||
|
||||
if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType()) {
|
||||
// Find all of the overloaded operators visible from this
|
||||
// point. We perform both an operator-name lookup from the local
|
||||
|
@ -5638,19 +5643,26 @@ Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
|
|||
FunctionSet Functions;
|
||||
OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc);
|
||||
if (OverOp != OO_None) {
|
||||
LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
|
||||
Functions);
|
||||
if (S)
|
||||
LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
|
||||
Functions);
|
||||
DeclarationName OpName
|
||||
= Context.DeclarationNames.getCXXOperatorName(OverOp);
|
||||
ArgumentDependentLookup(OpName, /*Operator*/true, &Input, 1, Functions);
|
||||
}
|
||||
|
||||
|
||||
return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(input));
|
||||
}
|
||||
|
||||
|
||||
return CreateBuiltinUnaryOp(OpLoc, Opc, move(input));
|
||||
}
|
||||
|
||||
// Unary Operators. 'Tok' is the token for the operator.
|
||||
Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
|
||||
tok::TokenKind Op, ExprArg input) {
|
||||
return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), move(input));
|
||||
}
|
||||
|
||||
/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
|
||||
Sema::OwningExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc,
|
||||
SourceLocation LabLoc,
|
||||
|
|
|
@ -4787,11 +4787,20 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
|
|||
// If either side is type-dependent, create an appropriate dependent
|
||||
// expression.
|
||||
if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
|
||||
// .* cannot be overloaded.
|
||||
if (Opc == BinaryOperator::PtrMemD)
|
||||
return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
|
||||
Context.DependentTy, OpLoc));
|
||||
|
||||
if (Functions.empty()) {
|
||||
// If there are no functions to store, just build a dependent
|
||||
// BinaryOperator or CompoundAssignment.
|
||||
if (Opc <= BinaryOperator::Assign || Opc > BinaryOperator::OrAssign)
|
||||
return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
|
||||
Context.DependentTy, OpLoc));
|
||||
|
||||
return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc,
|
||||
Context.DependentTy,
|
||||
Context.DependentTy,
|
||||
Context.DependentTy,
|
||||
OpLoc));
|
||||
}
|
||||
|
||||
OverloadedFunctionDecl *Overloads
|
||||
= OverloadedFunctionDecl::Create(Context, CurContext, OpName);
|
||||
for (FunctionSet::iterator Func = Functions.begin(),
|
||||
|
|
|
@ -877,7 +877,7 @@ public:
|
|||
OwningExprResult RebuildUnaryOperator(SourceLocation OpLoc,
|
||||
UnaryOperator::Opcode Opc,
|
||||
ExprArg SubExpr) {
|
||||
return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, move(SubExpr));
|
||||
return getSema().BuildUnaryOp(/*Scope=*/0, OpLoc, Opc, move(SubExpr));
|
||||
}
|
||||
|
||||
/// \brief Build a new sizeof or alignof expression with a type argument.
|
||||
|
@ -986,15 +986,8 @@ public:
|
|||
OwningExprResult RebuildBinaryOperator(SourceLocation OpLoc,
|
||||
BinaryOperator::Opcode Opc,
|
||||
ExprArg LHS, ExprArg RHS) {
|
||||
OwningExprResult Result
|
||||
= getSema().CreateBuiltinBinOp(OpLoc, Opc, (Expr *)LHS.get(),
|
||||
(Expr *)RHS.get());
|
||||
if (Result.isInvalid())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
LHS.release();
|
||||
RHS.release();
|
||||
return move(Result);
|
||||
return getSema().BuildBinOp(/*Scope=*/0, OpLoc, Opc,
|
||||
LHS.takeAs<Expr>(), RHS.takeAs<Expr>());
|
||||
}
|
||||
|
||||
/// \brief Build a new conditional operator expression.
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
template<int I, int J>
|
||||
struct Bitfields {
|
||||
int simple : I; // expected-error{{bit-field 'simple' has zero width}}
|
||||
|
@ -69,3 +68,29 @@ void test_BitfieldNeg() {
|
|||
(void)sizeof(BitfieldNeg2<int, -5>); // okay
|
||||
(void)sizeof(BitfieldNeg2<int, 5>); // expected-note{{in instantiation of template class 'struct BitfieldNeg2<int, 5>' requested here}}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void increment(T &x) {
|
||||
(void)++x;
|
||||
}
|
||||
|
||||
struct Incrementable {
|
||||
Incrementable &operator++();
|
||||
};
|
||||
|
||||
void test_increment(Incrementable inc) {
|
||||
increment(inc);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void add(const T &x) {
|
||||
(void)(x + x);
|
||||
}
|
||||
|
||||
struct Addable {
|
||||
Addable operator+(const Addable&) const;
|
||||
};
|
||||
|
||||
void test_add(Addable &a) {
|
||||
add(a);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue