Skip to content

Commit acf0ee5

Browse files
committed
Track the location of the context requiring an implicit conversion and use it
to white-list conversions required by system headers. rdar://problem/8232669 llvm-svn: 116029
1 parent 6b1b953 commit acf0ee5

File tree

8 files changed

+84
-36
lines changed

8 files changed

+84
-36
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4472,7 +4472,7 @@ class Sema {
44724472
void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
44734473
SourceLocation ReturnLoc);
44744474
void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex);
4475-
void CheckImplicitConversions(Expr *E);
4475+
void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
44764476

44774477
/// \brief The parser's current scope.
44784478
///

clang/lib/Sema/SemaChecking.cpp

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2434,7 +2434,7 @@ bool IsSameFloatAfterCast(const APValue &value,
24342434
IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt));
24352435
}
24362436

2437-
void AnalyzeImplicitConversions(Sema &S, Expr *E);
2437+
void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC);
24382438

24392439
static bool IsZero(Sema &S, Expr *E) {
24402440
// Suppress cases where we are comparing against an enum constant.
@@ -2487,8 +2487,8 @@ void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) {
24872487
/// Analyze the operands of the given comparison. Implements the
24882488
/// fallback case from AnalyzeComparison.
24892489
void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) {
2490-
AnalyzeImplicitConversions(S, E->getLHS());
2491-
AnalyzeImplicitConversions(S, E->getRHS());
2490+
AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc());
2491+
AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
24922492
}
24932493

24942494
/// \brief Implements -Wsign-compare.
@@ -2533,8 +2533,8 @@ void AnalyzeComparison(Sema &S, BinaryOperator *E) {
25332533

25342534
// Go ahead and analyze implicit conversions in the operands. Note
25352535
// that we skip the implicit conversions on both sides.
2536-
AnalyzeImplicitConversions(S, lex);
2537-
AnalyzeImplicitConversions(S, rex);
2536+
AnalyzeImplicitConversions(S, lex, E->getOperatorLoc());
2537+
AnalyzeImplicitConversions(S, rex, E->getOperatorLoc());
25382538

25392539
// If the signed range is non-negative, -Wsign-compare won't fire,
25402540
// but we should still check for comparisons which are always true
@@ -2564,27 +2564,36 @@ void AnalyzeComparison(Sema &S, BinaryOperator *E) {
25642564
}
25652565

25662566
/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
2567-
void DiagnoseImpCast(Sema &S, Expr *E, QualType T, unsigned diag) {
2568-
S.Diag(E->getExprLoc(), diag) << E->getType() << T << E->getSourceRange();
2567+
void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext,
2568+
unsigned diag) {
2569+
S.Diag(E->getExprLoc(), diag)
2570+
<< E->getType() << T << E->getSourceRange() << SourceRange(CContext);
25692571
}
25702572

25712573
void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
2572-
bool *ICContext = 0) {
2574+
SourceLocation CC, bool *ICContext = 0) {
25732575
if (E->isTypeDependent() || E->isValueDependent()) return;
25742576

25752577
const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr();
25762578
const Type *Target = S.Context.getCanonicalType(T).getTypePtr();
25772579
if (Source == Target) return;
25782580
if (Target->isDependentType()) return;
25792581

2582+
// If the conversion context location is invalid or instantiated
2583+
// from a system macro, don't complain.
2584+
if (CC.isInvalid() ||
2585+
(CC.isMacroID() && S.Context.getSourceManager().isInSystemHeader(
2586+
S.Context.getSourceManager().getSpellingLoc(CC))))
2587+
return;
2588+
25802589
// Never diagnose implicit casts to bool.
25812590
if (Target->isSpecificBuiltinType(BuiltinType::Bool))
25822591
return;
25832592

25842593
// Strip vector types.
25852594
if (isa<VectorType>(Source)) {
25862595
if (!isa<VectorType>(Target))
2587-
return DiagnoseImpCast(S, E, T, diag::warn_impcast_vector_scalar);
2596+
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar);
25882597

25892598
Source = cast<VectorType>(Source)->getElementType().getTypePtr();
25902599
Target = cast<VectorType>(Target)->getElementType().getTypePtr();
@@ -2593,7 +2602,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
25932602
// Strip complex types.
25942603
if (isa<ComplexType>(Source)) {
25952604
if (!isa<ComplexType>(Target))
2596-
return DiagnoseImpCast(S, E, T, diag::warn_impcast_complex_scalar);
2605+
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_complex_scalar);
25972606

25982607
Source = cast<ComplexType>(Source)->getElementType().getTypePtr();
25992608
Target = cast<ComplexType>(Target)->getElementType().getTypePtr();
@@ -2621,15 +2630,15 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
26212630
return;
26222631
}
26232632

2624-
DiagnoseImpCast(S, E, T, diag::warn_impcast_float_precision);
2633+
DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision);
26252634
}
26262635
return;
26272636
}
26282637

26292638
// If the target is integral, always warn.
26302639
if ((TargetBT && TargetBT->isInteger()))
26312640
// TODO: don't warn for integer values?
2632-
DiagnoseImpCast(S, E, T, diag::warn_impcast_float_integer);
2641+
DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_integer);
26332642

26342643
return;
26352644
}
@@ -2644,8 +2653,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
26442653
// People want to build with -Wshorten-64-to-32 and not -Wconversion
26452654
// and by god we'll let them.
26462655
if (SourceRange.Width == 64 && TargetRange.Width == 32)
2647-
return DiagnoseImpCast(S, E, T, diag::warn_impcast_integer_64_32);
2648-
return DiagnoseImpCast(S, E, T, diag::warn_impcast_integer_precision);
2656+
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_64_32);
2657+
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision);
26492658
}
26502659

26512660
if ((TargetRange.NonNegative && !SourceRange.NonNegative) ||
@@ -2663,7 +2672,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
26632672
*ICContext = true;
26642673
}
26652674

2666-
return DiagnoseImpCast(S, E, T, DiagID);
2675+
return DiagnoseImpCast(S, E, T, CC, DiagID);
26672676
}
26682677

26692678
return;
@@ -2672,24 +2681,26 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
26722681
void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T);
26732682

26742683
void CheckConditionalOperand(Sema &S, Expr *E, QualType T,
2675-
bool &ICContext) {
2684+
SourceLocation CC, bool &ICContext) {
26762685
E = E->IgnoreParenImpCasts();
26772686

26782687
if (isa<ConditionalOperator>(E))
26792688
return CheckConditionalOperator(S, cast<ConditionalOperator>(E), T);
26802689

2681-
AnalyzeImplicitConversions(S, E);
2690+
AnalyzeImplicitConversions(S, E, CC);
26822691
if (E->getType() != T)
2683-
return CheckImplicitConversion(S, E, T, &ICContext);
2692+
return CheckImplicitConversion(S, E, T, CC, &ICContext);
26842693
return;
26852694
}
26862695

26872696
void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T) {
2688-
AnalyzeImplicitConversions(S, E->getCond());
2697+
SourceLocation CC = E->getQuestionLoc();
2698+
2699+
AnalyzeImplicitConversions(S, E->getCond(), CC);
26892700

26902701
bool Suspicious = false;
2691-
CheckConditionalOperand(S, E->getTrueExpr(), T, Suspicious);
2692-
CheckConditionalOperand(S, E->getFalseExpr(), T, Suspicious);
2702+
CheckConditionalOperand(S, E->getTrueExpr(), T, CC, Suspicious);
2703+
CheckConditionalOperand(S, E->getFalseExpr(), T, CC, Suspicious);
26932704

26942705
// If -Wconversion would have warned about either of the candidates
26952706
// for a signedness conversion to the context type...
@@ -2708,10 +2719,10 @@ void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T) {
27082719
if (E->getType() != T) {
27092720
Suspicious = false;
27102721
CheckImplicitConversion(S, E->getTrueExpr()->IgnoreParenImpCasts(),
2711-
E->getType(), &Suspicious);
2722+
E->getType(), CC, &Suspicious);
27122723
if (!Suspicious)
27132724
CheckImplicitConversion(S, E->getFalseExpr()->IgnoreParenImpCasts(),
2714-
E->getType(), &Suspicious);
2725+
E->getType(), CC, &Suspicious);
27152726
if (!Suspicious)
27162727
return;
27172728
}
@@ -2727,7 +2738,7 @@ void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T) {
27272738
/// AnalyzeImplicitConversions - Find and report any interesting
27282739
/// implicit conversions in the given expression. There are a couple
27292740
/// of competing diagnostics here, -Wconversion and -Wsign-compare.
2730-
void AnalyzeImplicitConversions(Sema &S, Expr *OrigE) {
2741+
void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
27312742
QualType T = OrigE->getType();
27322743
Expr *E = OrigE->IgnoreParenImpCasts();
27332744

@@ -2743,14 +2754,14 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE) {
27432754
// The non-canonical typecheck is just an optimization;
27442755
// CheckImplicitConversion will filter out dead implicit conversions.
27452756
if (E->getType() != T)
2746-
CheckImplicitConversion(S, E, T);
2757+
CheckImplicitConversion(S, E, T, CC);
27472758

27482759
// Now continue drilling into this expression.
27492760

27502761
// Skip past explicit casts.
27512762
if (isa<ExplicitCastExpr>(E)) {
27522763
E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts();
2753-
return AnalyzeImplicitConversions(S, E);
2764+
return AnalyzeImplicitConversions(S, E, CC);
27542765
}
27552766

27562767
// Do a somewhat different check with comparison operators.
@@ -2767,17 +2778,22 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE) {
27672778
if (isa<SizeOfAlignOfExpr>(E)) return;
27682779

27692780
// Now just recurse over the expression's children.
2781+
CC = E->getExprLoc();
27702782
for (Stmt::child_iterator I = E->child_begin(), IE = E->child_end();
27712783
I != IE; ++I)
2772-
AnalyzeImplicitConversions(S, cast<Expr>(*I));
2784+
AnalyzeImplicitConversions(S, cast<Expr>(*I), CC);
27732785
}
27742786

27752787
} // end anonymous namespace
27762788

27772789
/// Diagnoses "dangerous" implicit conversions within the given
27782790
/// expression (which is a full expression). Implements -Wconversion
27792791
/// and -Wsign-compare.
2780-
void Sema::CheckImplicitConversions(Expr *E) {
2792+
///
2793+
/// \param CC the "context" location of the implicit conversion, i.e.
2794+
/// the most location of the syntactic entity requiring the implicit
2795+
/// conversion
2796+
void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) {
27812797
// Don't diagnose in unevaluated contexts.
27822798
if (ExprEvalContexts.back().Context == Sema::Unevaluated)
27832799
return;
@@ -2786,7 +2802,8 @@ void Sema::CheckImplicitConversions(Expr *E) {
27862802
if (E->isTypeDependent() || E->isValueDependent())
27872803
return;
27882804

2789-
AnalyzeImplicitConversions(*this, E);
2805+
// This is not the right CC for (e.g.) a variable initialization.
2806+
AnalyzeImplicitConversions(*this, E, CC);
27902807
}
27912808

27922809
/// CheckParmsForFunctionDef - Check that the parameters of the given

clang/lib/Sema/SemaDecl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4326,6 +4326,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
43264326
Init->setType(DclT);
43274327
}
43284328

4329+
// Check any implicit conversions within the expression.
4330+
CheckImplicitConversions(Init, VDecl->getLocation());
4331+
43294332
Init = MaybeCreateCXXExprWithTemporaries(Init);
43304333
// Attach the initializer to the decl.
43314334
VDecl->setInit(Init);

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
136136
return true;
137137
Arg = Result.takeAs<Expr>();
138138

139+
CheckImplicitConversions(Arg, EqualLoc);
139140
Arg = MaybeCreateCXXExprWithTemporaries(Arg);
140141

141142
// Okay: add the default argument to the parameter
@@ -1276,6 +1277,8 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
12761277
MultiExprArg(*this, Args, NumArgs), 0);
12771278
if (MemberInit.isInvalid())
12781279
return true;
1280+
1281+
CheckImplicitConversions(MemberInit.get(), LParenLoc);
12791282

12801283
// C++0x [class.base.init]p7:
12811284
// The initialization of each base and member constitutes a
@@ -1407,6 +1410,8 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
14071410
MultiExprArg(*this, Args, NumArgs), 0);
14081411
if (BaseInit.isInvalid())
14091412
return true;
1413+
1414+
CheckImplicitConversions(BaseInit.get(), LParenLoc);
14101415

14111416
// C++0x [class.base.init]p7:
14121417
// The initialization of each base and member constitutes a
@@ -5356,6 +5361,7 @@ bool Sema::InitializeVarWithConstructor(VarDecl *VD,
53565361
return true;
53575362

53585363
Expr *Temp = TempResult.takeAs<Expr>();
5364+
CheckImplicitConversions(Temp, VD->getLocation());
53595365
MarkDeclarationReferenced(VD->getLocation(), Constructor);
53605366
Temp = MaybeCreateCXXExprWithTemporaries(Temp);
53615367
VD->setInit(Temp);
@@ -5489,6 +5495,8 @@ void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl,
54895495
VDecl->setInvalidDecl();
54905496
return;
54915497
}
5498+
5499+
CheckImplicitConversions(Result.get(), LParenLoc);
54925500

54935501
Result = MaybeCreateCXXExprWithTemporaries(Result.get());
54945502
VDecl->setInit(Result.takeAs<Expr>());
@@ -6834,7 +6842,7 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
68346842
// is required (e.g., because it would call a trivial default constructor)
68356843
if (!MemberInit.get() || MemberInit.isInvalid())
68366844
continue;
6837-
6845+
68386846
Member =
68396847
new (Context) CXXBaseOrMemberInitializer(Context,
68406848
Field, SourceLocation(),

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2962,9 +2962,6 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
29622962
Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr) {
29632963
assert(SubExpr && "sub expression can't be null!");
29642964

2965-
// Check any implicit conversions within the expression.
2966-
CheckImplicitConversions(SubExpr);
2967-
29682965
unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries;
29692966
assert(ExprTemporaries.size() >= FirstTemporary);
29702967
if (ExprTemporaries.size() == FirstTemporary)
@@ -3381,5 +3378,7 @@ ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation,
33813378

33823379
ExprResult Sema::ActOnFinishFullExpr(Expr *FullExpr) {
33833380
if (!FullExpr) return ExprError();
3381+
3382+
CheckImplicitConversions(FullExpr);
33843383
return MaybeCreateCXXExprWithTemporaries(FullExpr);
33853384
}

clang/lib/Sema/SemaStmt.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
446446
Cond = CondResult.take();
447447

448448
if (!CondVar) {
449+
CheckImplicitConversions(Cond, SwitchLoc);
449450
CondResult = MaybeCreateCXXExprWithTemporaries(Cond);
450451
if (CondResult.isInvalid())
451452
return StmtError();
@@ -889,6 +890,7 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
889890
if (CheckBooleanCondition(Cond, DoLoc))
890891
return StmtError();
891892

893+
CheckImplicitConversions(Cond, DoLoc);
892894
ExprResult CondResult = MaybeCreateCXXExprWithTemporaries(Cond);
893895
if (CondResult.isInvalid())
894896
return StmtError();
@@ -1173,8 +1175,10 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
11731175
return StmtError();
11741176
}
11751177

1176-
if (RetValExp)
1178+
if (RetValExp) {
1179+
CheckImplicitConversions(RetValExp, ReturnLoc);
11771180
RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp);
1181+
}
11781182

11791183
RetValExp = Res.takeAs<Expr>();
11801184
if (RetValExp)
@@ -1227,6 +1231,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
12271231
<< RetValExp->getSourceRange();
12281232
}
12291233

1234+
CheckImplicitConversions(RetValExp, ReturnLoc);
12301235
RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp);
12311236
}
12321237

@@ -1269,8 +1274,10 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
12691274
CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
12701275
}
12711276

1272-
if (RetValExp)
1277+
if (RetValExp) {
1278+
CheckImplicitConversions(RetValExp, ReturnLoc);
12731279
RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp);
1280+
}
12741281
Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate);
12751282
}
12761283

clang/test/Sema/Inputs/conversion.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/* Fake system header for Sema/conversion.c */
22

33
#define LONG_MAX __LONG_MAX__
4+
#define SETBIT(set,bit) do { int i = bit; set[i/(8*sizeof(set[0]))] |= (1 << (i%(8*sizeof(set)))); } while(0)

clang/test/Sema/conversion.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,3 +297,16 @@ void test_7904686(void) {
297297
unsigned u2 = -1; // expected-warning {{implicit conversion changes signedness}}
298298
u2 = -1; // expected-warning {{implicit conversion changes signedness}}
299299
}
300+
301+
// <rdar://problem/8232669>: don't warn about conversions required by
302+
// contexts in system headers
303+
void test_8232669(void) {
304+
unsigned bitset[20];
305+
SETBIT(bitset, 0);
306+
307+
unsigned y = 50;
308+
SETBIT(bitset, y);
309+
310+
#define USER_SETBIT(set,bit) do { int i = bit; set[i/(8*sizeof(set[0]))] |= (1 << (i%(8*sizeof(set)))); } while(0)
311+
USER_SETBIT(bitset, 0); // expected-warning 2 {{implicit conversion changes signedness}}
312+
}

0 commit comments

Comments
 (0)