void VisitBinaryOperator(BinaryOperator *bo);
void VisitCastExpr(CastExpr *ce);
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *se);
+ void VisitCXXTypeidExpr(CXXTypeidExpr *E);
void BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt *fs);
bool isTrackedVar(const VarDecl *vd) {
}
}
+void TransferFunctions::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+ // typeid(expression) is potentially evaluated when the argument is
+ // a glvalue of polymorphic type. (C++ 5.2.8p2-3)
+ if (!E->isTypeOperand() && E->Classify(ac.getASTContext()).isGLValue()) {
+ QualType SubExprTy = E->getExprOperand()->getType();
+ if (const RecordType *Record = SubExprTy->getAs<RecordType>())
+ if (cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic())
+ Visit(E->getExprOperand());
+ }
+}
+
//------------------------------------------------------------------------====//
// High-level "driver" logic for uninitialized values analysis.
//====------------------------------------------------------------------------//
// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -fsyntax-only -fcxx-exceptions %s -verify
+// Stub out types for 'typeid' to work.
+namespace std { class type_info {}; }
+
int test1_aux(int &x);
int test1() {
int x;
return x; // no-warning
}
+// Don't warn on unevaluated contexts.
+void unevaluated_tests() {
+ int x;
+ (void)sizeof(x);
+ (void)typeid(x);
+}
+
+// Warn for glvalue arguments to typeid whose type is polymorphic.
+struct A { virtual ~A() {} };
+void polymorphic_test() {
+ A *a; // expected-note{{declared here}} expected-note{{add initialization}}
+ (void)typeid(*a); // expected-warning{{variable 'a' is uninitialized when used here }}
+}
+
// Handle cases where the CFG may constant fold some branches, thus
// mitigating the need for some path-sensitivity in the analysis.
unsigned test3_aux();