Skip to content

Commit 1a99f44

Browse files
author
Sebastian Redl
committed
Fix a crash bug when comparing overload quality of conversion operators with conversion constructors.
Remove an atrocious amount of trailing whitespace in the overloaded operator mangler. Sorry, couldn't help myself. Change the DeclType parameter of Sema::CheckReferenceInit to be passed by value instead of reference. It wasn't changed anywhere. Let the parser handle C++'s irregular grammar around assignment-expression and conditional-expression. And finally, the reason for all this stuff: implement C++ semantics for the conditional operator. The implementation is complete except for determining lvalueness. llvm-svn: 69299
1 parent 8d25b09 commit 1a99f44

File tree

12 files changed

+587
-80
lines changed

12 files changed

+587
-80
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1123,11 +1123,19 @@ def err_bad_memptr_rhs : Error<
11231123
"right hand operand to %0 has non pointer-to-member type %1">;
11241124
def err_memptr_rhs_incomplete : Error<
11251125
"right hand operand is a pointer to member of incomplete type %0">;
1126-
11271126
def err_bad_memptr_lhs : Error<
11281127
"left hand operand to %0 must be a %select{|pointer to }1class "
11291128
"compatible with the right hand operand, but is %2">;
11301129

1130+
def err_conditional_void_nonvoid : Error<
1131+
"%select{left|right}1 operand to ? is void, but %select{right|left}1 operand "
1132+
"is of type %0">;
1133+
def err_conditional_ambiguous : Error<
1134+
"conditional expression is ambiguous; %0 can be converted to %1 "
1135+
"and vice versa">;
1136+
def err_conditional_ambiguous_ovl : Error<
1137+
"conditional expression is ambiguous; %0 and %1 can be converted to several "
1138+
"common types">;
11311139

11321140
def err_invalid_use_of_function_type : Error<
11331141
"a function type is not allowed here">;

clang/include/clang/Basic/OperatorKinds.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ OVERLOADED_OPERATOR(ArrowStar , "->*" , arrowstar , false, t
9898
OVERLOADED_OPERATOR(Arrow , "->" , arrow , true , false, true)
9999
OVERLOADED_OPERATOR_MULTI(Call , "()" , true , true , true)
100100
OVERLOADED_OPERATOR_MULTI(Subscript , "[]" , false, true , true)
101+
// ?: can *not* be overloaded, but we need the overload
102+
// resolution machinery for it.
103+
OVERLOADED_OPERATOR_MULTI(Conditional , "?" , false, true , false)
101104

102105
#undef OVERLOADED_OPERATOR_MULTI
103106
#undef OVERLOADED_OPERATOR

clang/lib/CodeGen/Mangle.cpp

Lines changed: 56 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -283,97 +283,98 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC) {
283283
void
284284
CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
285285
switch (OO) {
286-
// <operator-name> ::= nw # new
286+
// <operator-name> ::= nw # new
287287
case OO_New: Out << "nw"; break;
288288
// ::= na # new[]
289289
case OO_Array_New: Out << "na"; break;
290-
// ::= dl # delete
290+
// ::= dl # delete
291291
case OO_Delete: Out << "dl"; break;
292-
// ::= da # delete[]
292+
// ::= da # delete[]
293293
case OO_Array_Delete: Out << "da"; break;
294294
// ::= ps # + (unary)
295295
// ::= pl # +
296296
case OO_Plus: Out << (Arity == 1? "ps" : "pl"); break;
297-
// ::= ng # - (unary)
298-
// ::= mi # -
297+
// ::= ng # - (unary)
298+
// ::= mi # -
299299
case OO_Minus: Out << (Arity == 1? "ng" : "mi"); break;
300-
// ::= ad # & (unary)
301-
// ::= an # &
300+
// ::= ad # & (unary)
301+
// ::= an # &
302302
case OO_Amp: Out << (Arity == 1? "ad" : "an"); break;
303-
// ::= de # * (unary)
304-
// ::= ml # *
303+
// ::= de # * (unary)
304+
// ::= ml # *
305305
case OO_Star: Out << (Arity == 1? "de" : "ml"); break;
306-
// ::= co # ~
306+
// ::= co # ~
307307
case OO_Tilde: Out << "co"; break;
308-
// ::= dv # /
308+
// ::= dv # /
309309
case OO_Slash: Out << "dv"; break;
310-
// ::= rm # %
310+
// ::= rm # %
311311
case OO_Percent: Out << "rm"; break;
312-
// ::= or # |
313-
case OO_Pipe: Out << "or"; break;
314-
// ::= eo # ^
312+
// ::= or # |
313+
case OO_Pipe: Out << "or"; break;
314+
// ::= eo # ^
315315
case OO_Caret: Out << "eo"; break;
316-
// ::= aS # =
316+
// ::= aS # =
317317
case OO_Equal: Out << "aS"; break;
318-
// ::= pL # +=
318+
// ::= pL # +=
319319
case OO_PlusEqual: Out << "pL"; break;
320-
// ::= mI # -=
320+
// ::= mI # -=
321321
case OO_MinusEqual: Out << "mI"; break;
322-
// ::= mL # *=
322+
// ::= mL # *=
323323
case OO_StarEqual: Out << "mL"; break;
324-
// ::= dV # /=
324+
// ::= dV # /=
325325
case OO_SlashEqual: Out << "dV"; break;
326-
// ::= rM # %=
327-
case OO_PercentEqual: Out << "rM"; break;
328-
// ::= aN # &=
329-
case OO_AmpEqual: Out << "aN"; break;
330-
// ::= oR # |=
331-
case OO_PipeEqual: Out << "oR"; break;
332-
// ::= eO # ^=
333-
case OO_CaretEqual: Out << "eO"; break;
334-
// ::= ls # <<
326+
// ::= rM # %=
327+
case OO_PercentEqual: Out << "rM"; break;
328+
// ::= aN # &=
329+
case OO_AmpEqual: Out << "aN"; break;
330+
// ::= oR # |=
331+
case OO_PipeEqual: Out << "oR"; break;
332+
// ::= eO # ^=
333+
case OO_CaretEqual: Out << "eO"; break;
334+
// ::= ls # <<
335335
case OO_LessLess: Out << "ls"; break;
336-
// ::= rs # >>
337-
case OO_GreaterGreater: Out << "rs"; break;
338-
// ::= lS # <<=
339-
case OO_LessLessEqual: Out << "lS"; break;
340-
// ::= rS # >>=
341-
case OO_GreaterGreaterEqual: Out << "rS"; break;
336+
// ::= rs # >>
337+
case OO_GreaterGreater: Out << "rs"; break;
338+
// ::= lS # <<=
339+
case OO_LessLessEqual: Out << "lS"; break;
340+
// ::= rS # >>=
341+
case OO_GreaterGreaterEqual: Out << "rS"; break;
342342
// ::= eq # ==
343343
case OO_EqualEqual: Out << "eq"; break;
344-
// ::= ne # !=
345-
case OO_ExclaimEqual: Out << "ne"; break;
346-
// ::= lt # <
344+
// ::= ne # !=
345+
case OO_ExclaimEqual: Out << "ne"; break;
346+
// ::= lt # <
347347
case OO_Less: Out << "lt"; break;
348-
// ::= gt # >
348+
// ::= gt # >
349349
case OO_Greater: Out << "gt"; break;
350-
// ::= le # <=
350+
// ::= le # <=
351351
case OO_LessEqual: Out << "le"; break;
352-
// ::= ge # >=
352+
// ::= ge # >=
353353
case OO_GreaterEqual: Out << "ge"; break;
354-
// ::= nt # !
354+
// ::= nt # !
355355
case OO_Exclaim: Out << "nt"; break;
356-
// ::= aa # &&
356+
// ::= aa # &&
357357
case OO_AmpAmp: Out << "aa"; break;
358-
// ::= oo # ||
359-
case OO_PipePipe: Out << "oo"; break;
360-
// ::= pp # ++
361-
case OO_PlusPlus: Out << "pp"; break;
362-
// ::= mm # --
358+
// ::= oo # ||
359+
case OO_PipePipe: Out << "oo"; break;
360+
// ::= pp # ++
361+
case OO_PlusPlus: Out << "pp"; break;
362+
// ::= mm # --
363363
case OO_MinusMinus: Out << "mm"; break;
364-
// ::= cm # ,
365-
case OO_Comma: Out << "cm"; break;
366-
// ::= pm # ->*
364+
// ::= cm # ,
365+
case OO_Comma: Out << "cm"; break;
366+
// ::= pm # ->*
367367
case OO_ArrowStar: Out << "pm"; break;
368-
// ::= pt # ->
368+
// ::= pt # ->
369369
case OO_Arrow: Out << "pt"; break;
370-
// ::= cl # ()
370+
// ::= cl # ()
371371
case OO_Call: Out << "cl"; break;
372-
// ::= ix # []
372+
// ::= ix # []
373373
case OO_Subscript: Out << "ix"; break;
374374
// UNSUPPORTED: ::= qu # ?
375375

376-
case OO_None:
376+
case OO_None:
377+
case OO_Conditional:
377378
case NUM_OVERLOADED_OPERATORS:
378379
assert(false && "Not an overloaded operator");
379380
break;

clang/lib/Parse/ParseExpr.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
186186
/// logical-OR-expression
187187
/// logical-OR-expression '?' expression ':' conditional-expression
188188
/// [GNU] logical-OR-expression '?' ':' conditional-expression
189+
/// [C++] the third operand is an assignment-expression
189190
///
190191
/// assignment-expression: [C99 6.5.16]
191192
/// conditional-expression
@@ -332,7 +333,17 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) {
332333
}
333334

334335
// Parse another leaf here for the RHS of the operator.
335-
OwningExprResult RHS(ParseCastExpression(false));
336+
// ParseCastExpression works here because all RHS expressions in C have it
337+
// as a prefix, at least. However, in C++, an assignment-expression could
338+
// be a throw-expression, which is not a valid cast-expression.
339+
// Therefore we need some special-casing here.
340+
// Also note that the third operand of the conditional operator is
341+
// an assignment-expression in C++.
342+
OwningExprResult RHS(Actions);
343+
if (getLang().CPlusPlus && NextTokPrec <= prec::Conditional)
344+
RHS = ParseAssignmentExpression();
345+
else
346+
RHS = ParseCastExpression(false);
336347
if (RHS.isInvalid())
337348
return move(RHS);
338349

clang/lib/Sema/Sema.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2382,6 +2382,8 @@ class Sema : public Action {
23822382
Expr *lex, Expr *&rex, SourceLocation OpLoc);
23832383
QualType CheckConditionalOperands( // C99 6.5.15
23842384
Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc);
2385+
QualType CXXCheckConditionalOperands( // C++ 5.16
2386+
Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc);
23852387

23862388
/// type checking for vector binary operators.
23872389
inline QualType CheckVectorOperands(SourceLocation l, Expr *&lex, Expr *&rex);
@@ -2435,7 +2437,7 @@ class Sema : public Action {
24352437
ReferenceCompareResult CompareReferenceRelationship(QualType T1, QualType T2,
24362438
bool& DerivedToBase);
24372439

2438-
bool CheckReferenceInit(Expr *&simpleInit_or_initList, QualType &declType,
2440+
bool CheckReferenceInit(Expr *&simpleInit_or_initList, QualType declType,
24392441
ImplicitConversionSequence *ICS = 0,
24402442
bool SuppressUserConversions = false,
24412443
bool AllowExplicit = false,

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2018,7 +2018,7 @@ Sema::CompareReferenceRelationship(QualType T1, QualType T2,
20182018
/// conversion functions.
20192019
/// When @p ForceRValue, we unconditionally treat the initializer as an rvalue.
20202020
bool
2021-
Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
2021+
Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
20222022
ImplicitConversionSequence *ICS,
20232023
bool SuppressUserConversions,
20242024
bool AllowExplicit, bool ForceRValue) {

clang/lib/Sema/SemaExpr.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2588,6 +2588,10 @@ Sema::ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
25882588
/// C99 6.5.15
25892589
QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
25902590
SourceLocation QuestionLoc) {
2591+
// C++ is sufficiently different to merit its own checker.
2592+
if (getLangOptions().CPlusPlus)
2593+
return CXXCheckConditionalOperands(Cond, LHS, RHS, QuestionLoc);
2594+
25912595
UsualUnaryConversions(Cond);
25922596
UsualUnaryConversions(LHS);
25932597
UsualUnaryConversions(RHS);
@@ -2596,17 +2600,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
25962600
QualType RHSTy = RHS->getType();
25972601

25982602
// first, check the condition.
2599-
if (!Cond->isTypeDependent()) {
2600-
if (!CondTy->isScalarType()) { // C99 6.5.15p2
2601-
Diag(Cond->getLocStart(), diag::err_typecheck_cond_expect_scalar)
2602-
<< CondTy;
2603-
return QualType();
2604-
}
2603+
if (!CondTy->isScalarType()) { // C99 6.5.15p2
2604+
Diag(Cond->getLocStart(), diag::err_typecheck_cond_expect_scalar)
2605+
<< CondTy;
2606+
return QualType();
26052607
}
26062608

26072609
// Now check the two expressions.
2608-
if ((LHS && LHS->isTypeDependent()) || (RHS && RHS->isTypeDependent()))
2609-
return Context.DependentTy;
26102610

26112611
// If both operands have arithmetic type, do the usual arithmetic conversions
26122612
// to find a common type: C99 6.5.15p3,5.

0 commit comments

Comments
 (0)