// For conditional operators, the cast can be outside the conditional
// operator if both expressions are DeclRefExpr's.
void HandleValue(Expr *E) {
- if (isReferenceType)
- return;
E = E->IgnoreParens();
if (DeclRefExpr* DRE = dyn_cast<DeclRefExpr>(E)) {
HandleDeclRefExpr(DRE);
if (BinaryConditionalOperator *BCO =
dyn_cast<BinaryConditionalOperator>(E)) {
+ Visit(BCO->getCond());
HandleValue(BCO->getFalseExpr());
return;
}
HandleDeclRefExpr(DRE);
return;
}
+
+ Visit(E);
}
- // Reference types are handled here since all uses of references are
- // bad, not just r-value uses.
+ // Reference types not handled in HandleValue are handled here since all
+ // uses of references are bad, not just r-value uses.
void VisitDeclRefExpr(DeclRefExpr *E) {
if (isReferenceType)
HandleDeclRefExpr(E);
void VisitImplicitCastExpr(ImplicitCastExpr *E) {
if (E->getCastKind() == CK_LValueToRValue ||
- (isRecordType && E->getCastKind() == CK_NoOp))
+ (isRecordType && E->getCastKind() == CK_NoOp)) {
HandleValue(E->getSubExpr());
+ return;
+ }
Inherited::VisitImplicitCastExpr(E);
}
if (FunctionDecl *FD = E->getDirectCallee()) {
if (FD->getIdentifier() && FD->getIdentifier()->isStr("move")) {
HandleValue(E->getArg(0));
+ return;
}
}
}
Inherited::VisitCallExpr(E);
}
+ // A custom visitor for BinaryConditionalOperator is needed because the
+ // regular visitor would check the condition and true expression separately
+ // but both point to the same place giving duplicate diagnostics.
+ void VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
+ Visit(E->getCond());
+ Visit(E->getFalseExpr());
+ }
+
void HandleDeclRefExpr(DeclRefExpr *DRE) {
Decl* ReferenceDecl = DRE->getDecl();
if (OrigDecl != ReferenceDecl) return;
int &e = d ?: e; // expected-warning{{reference 'e' is not yet bound to a value when used within its own initialization}}
int &f = f ?: d; // expected-warning{{reference 'f' is not yet bound to a value when used within its own initialization}}
+ int &return_ref1(int);
+ int &return_ref2(int&);
+
+ int &g = return_ref1(g); // expected-warning{{reference 'g' is not yet bound to a value when used within its own initialization}}
+ int &h = return_ref2(h); // expected-warning{{reference 'h' is not yet bound to a value when used within its own initialization}}
+
struct S {
S() : a(a) {} // expected-warning{{reference 'a' is not yet bound to a value when used here}}
int &a;