Skip to content

Instantly share code, notes, and snippets.

@vgvassilev
Created March 8, 2015 10:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vgvassilev/471feedc9de61a9590da to your computer and use it in GitHub Desktop.
Save vgvassilev/471feedc9de61a9590da to your computer and use it in GitHub Desktop.
Patch provided by Nick Lewycky (see [cfe-dev] CopyPaste detection clang static analyzer)
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h (revision 200870)
+++ include/clang/AST/Expr.h (working copy)
@@ -690,9 +690,9 @@
}
/// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return
- /// its subexpression. If that subexpression is also a ParenExpr,
- /// then this method recursively returns its subexpression, and so forth.
- /// Otherwise, the method returns the current Expr.
+ /// its subexpression. If that subexpression is also a ParenExpr,
+ /// then this method recursively returns its subexpression, and so forth.
+ /// Otherwise, the method returns the current Expr.
Expr *IgnoreParens() LLVM_READONLY;
/// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr
Index: include/clang/AST/Stmt.h
===================================================================
--- include/clang/AST/Stmt.h (revision 200870)
+++ include/clang/AST/Stmt.h (working copy)
@@ -431,8 +431,12 @@
/// parameters are identified by index/level rather than their
/// declaration pointers) or the exact representation of the statement as
/// written in the source.
+ ///
+ /// \param Macro whether the profile should include the source location of
+ /// the site of definition of any macros used in the expansion of this
+ /// statement.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
- bool Canonical) const;
+ bool Canonical, bool Macro) const;
};
/// DeclStmt - Adaptor class for mixing declarations with statements and
Index: include/clang/AST/StmtObjC.h
===================================================================
--- include/clang/AST/StmtObjC.h (revision 200870)
+++ include/clang/AST/StmtObjC.h (working copy)
@@ -324,7 +324,7 @@
Expr *getThrowExpr() { return reinterpret_cast<Expr*>(Throw); }
void setThrowExpr(Stmt *S) { Throw = S; }
- SourceLocation getThrowLoc() { return AtThrowLoc; }
+ SourceLocation getThrowLoc() const LLVM_READONLY { return AtThrowLoc; }
void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; }
SourceLocation getLocStart() const LLVM_READONLY { return AtThrowLoc; }
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td (revision 200870)
+++ include/clang/Basic/DiagnosticSemaKinds.td (working copy)
@@ -199,16 +199,16 @@
def warn_unused_private_field: Warning<"private field %0 is not used">,
InGroup<UnusedPrivateField>, DefaultIgnore;
-def warn_parameter_size: Warning<
+def warn_parameter_size : Warning<
"%0 is a large (%1 bytes) pass-by-value argument; "
"pass it by reference instead ?">, InGroup<LargeByValueCopy>;
-def warn_return_value_size: Warning<
+def warn_return_value_size : Warning<
"return value of %0 is a large (%1 bytes) pass-by-value object; "
"pass it by reference instead ?">, InGroup<LargeByValueCopy>;
-def warn_return_value_udt: Warning<
+def warn_return_value_udt : Warning<
"%0 has C-linkage specified, but returns user-defined type %1 which is "
"incompatible with C">, InGroup<ReturnTypeCLinkage>;
-def warn_return_value_udt_incomplete: Warning<
+def warn_return_value_udt_incomplete : Warning<
"%0 has C-linkage specified, but returns incomplete type %1 which could be "
"incompatible with C">, InGroup<ReturnTypeCLinkage>;
def warn_implicit_function_decl : Warning<
@@ -6850,4 +6850,10 @@
"not a Doxygen trailing comment">, InGroup<Documentation>, DefaultIgnore;
} // end of documentation issue category
+def warn_condition_same_stmt : Warning<
+ "same %select{statements|expressions}0 on either side of condition">,
+ InGroup<DiagGroup<"useless-condition">>;
+def note_code_here : Note<
+ "in %select{statement|expression}0 here">;
+
} // end of sema component.
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h (revision 200870)
+++ include/clang/Sema/Sema.h (working copy)
@@ -3078,6 +3078,8 @@
void DiagnoseEmptyLoopBody(const Stmt *S,
const Stmt *PossibleBody);
+ void CheckStatementsUnique(SourceLocation Loc, ArrayRef<Stmt*> Stmts);
+
ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) {
return DelayedDiagnostics.push(pool);
}
Index: lib/AST/StmtProfile.cpp
===================================================================
--- lib/AST/StmtProfile.cpp (revision 200870)
+++ lib/AST/StmtProfile.cpp (working copy)
@@ -27,11 +27,14 @@
llvm::FoldingSetNodeID &ID;
const ASTContext &Context;
bool Canonical;
+ bool Macro;
+ void VisitSourceLocation(SourceLocation Loc);
+
public:
StmtProfiler(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
- bool Canonical)
- : ID(ID), Context(Context), Canonical(Canonical) { }
+ bool Canonical, bool Macro)
+ : ID(ID), Context(Context), Canonical(Canonical), Macro(Macro) { }
void VisitStmt(const Stmt *S);
@@ -64,9 +67,22 @@
/// \brief Visit a single template argument.
void VisitTemplateArgument(const TemplateArgument &Arg);
- };
+ };
}
+void StmtProfiler::VisitSourceLocation(SourceLocation Loc) {
+ if (!Macro) return;
+
+ if (Loc.isInvalid() || !Loc.isMacroID()) {
+ ID.AddInteger(0);
+ return;
+ }
+
+ SourceLocation MacroDefLoc =
+ Context.getSourceManager().getImmediateSpellingLoc(Loc);
+ ID.AddInteger(MacroDefLoc.getRawEncoding());
+}
+
void StmtProfiler::VisitStmt(const Stmt *S) {
ID.AddInteger(S->getStmtClass());
for (Stmt::const_child_range C = S->children(); C; ++C) {
@@ -79,6 +95,8 @@
void StmtProfiler::VisitDeclStmt(const DeclStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getStartLoc());
+ VisitSourceLocation(S->getEndLoc());
for (DeclStmt::const_decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
D != DEnd; ++D)
VisitDecl(*D);
@@ -86,10 +104,13 @@
void StmtProfiler::VisitNullStmt(const NullStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getSemiLoc());
}
void StmtProfiler::VisitCompoundStmt(const CompoundStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getLBracLoc());
+ VisitSourceLocation(S->getRBracLoc());
}
void StmtProfiler::VisitSwitchCase(const SwitchCase *S) {
@@ -98,68 +119,94 @@
void StmtProfiler::VisitCaseStmt(const CaseStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getCaseLoc());
+ VisitSourceLocation(S->getEllipsisLoc());
+ VisitSourceLocation(S->getColonLoc());
}
void StmtProfiler::VisitDefaultStmt(const DefaultStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getDefaultLoc());
+ VisitSourceLocation(S->getColonLoc());
}
void StmtProfiler::VisitLabelStmt(const LabelStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getIdentLoc());
VisitDecl(S->getDecl());
}
void StmtProfiler::VisitAttributedStmt(const AttributedStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getAttrLoc());
// TODO: maybe visit attributes?
}
void StmtProfiler::VisitIfStmt(const IfStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getIfLoc());
+ VisitSourceLocation(S->getElseLoc());
VisitDecl(S->getConditionVariable());
}
void StmtProfiler::VisitSwitchStmt(const SwitchStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getSwitchLoc());
VisitDecl(S->getConditionVariable());
}
void StmtProfiler::VisitWhileStmt(const WhileStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getWhileLoc());
VisitDecl(S->getConditionVariable());
}
void StmtProfiler::VisitDoStmt(const DoStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getDoLoc());
+ VisitSourceLocation(S->getWhileLoc());
+ VisitSourceLocation(S->getRParenLoc());
}
void StmtProfiler::VisitForStmt(const ForStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getForLoc());
+ VisitSourceLocation(S->getLParenLoc());
+ VisitSourceLocation(S->getRParenLoc());
}
void StmtProfiler::VisitGotoStmt(const GotoStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getGotoLoc());
+ VisitSourceLocation(S->getLabelLoc());
VisitDecl(S->getLabel());
}
void StmtProfiler::VisitIndirectGotoStmt(const IndirectGotoStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getGotoLoc());
+ VisitSourceLocation(S->getStarLoc());
}
void StmtProfiler::VisitContinueStmt(const ContinueStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getContinueLoc());
}
void StmtProfiler::VisitBreakStmt(const BreakStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getBreakLoc());
}
void StmtProfiler::VisitReturnStmt(const ReturnStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getReturnLoc());
}
void StmtProfiler::VisitGCCAsmStmt(const GCCAsmStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getAsmLoc());
+ VisitSourceLocation(S->getRParenLoc());
ID.AddBoolean(S->isVolatile());
ID.AddBoolean(S->isSimple());
VisitStringLiteral(S->getAsmString());
@@ -181,23 +228,30 @@
void StmtProfiler::VisitMSAsmStmt(const MSAsmStmt *S) {
// FIXME: Implement MS style inline asm statement profiler.
VisitStmt(S);
+ VisitSourceLocation(S->getAsmLoc());
}
void StmtProfiler::VisitCXXCatchStmt(const CXXCatchStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getCatchLoc());
VisitType(S->getCaughtType());
}
void StmtProfiler::VisitCXXTryStmt(const CXXTryStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getTryLoc());
}
void StmtProfiler::VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getForLoc());
+ VisitSourceLocation(S->getColonLoc());
+ VisitSourceLocation(S->getRParenLoc());
}
void StmtProfiler::VisitMSDependentExistsStmt(const MSDependentExistsStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getKeywordLoc());
ID.AddBoolean(S->isIfExists());
VisitNestedNameSpecifier(S->getQualifierLoc().getNestedNameSpecifier());
VisitName(S->getNameInfo().getName());
@@ -205,14 +259,17 @@
void StmtProfiler::VisitSEHTryStmt(const SEHTryStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getTryLoc());
}
void StmtProfiler::VisitSEHFinallyStmt(const SEHFinallyStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getFinallyLoc());
}
void StmtProfiler::VisitSEHExceptStmt(const SEHExceptStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getExceptLoc());
}
void StmtProfiler::VisitCapturedStmt(const CapturedStmt *S) {
@@ -221,10 +278,14 @@
void StmtProfiler::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getForLoc());
+ VisitSourceLocation(S->getRParenLoc());
}
void StmtProfiler::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getAtCatchLoc());
+ VisitSourceLocation(S->getRParenLoc());
ID.AddBoolean(S->hasEllipsis());
if (S->getCatchParamDecl())
VisitType(S->getCatchParamDecl()->getType());
@@ -232,24 +293,29 @@
void StmtProfiler::VisitObjCAtFinallyStmt(const ObjCAtFinallyStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getAtFinallyLoc());
}
void StmtProfiler::VisitObjCAtTryStmt(const ObjCAtTryStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getAtTryLoc());
}
void
StmtProfiler::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getAtSynchronizedLoc());
}
void StmtProfiler::VisitObjCAtThrowStmt(const ObjCAtThrowStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getThrowLoc());
}
void
StmtProfiler::VisitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt *S) {
VisitStmt(S);
+ VisitSourceLocation(S->getAtLoc());
}
namespace {
@@ -304,6 +370,7 @@
void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLocation());
if (!Canonical)
VisitNestedNameSpecifier(S->getQualifier());
VisitDecl(S->getDecl());
@@ -313,16 +380,19 @@
void StmtProfiler::VisitPredefinedExpr(const PredefinedExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLocation());
ID.AddInteger(S->getIdentType());
}
void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLocation());
S->getValue().Profile(ID);
}
void StmtProfiler::VisitCharacterLiteral(const CharacterLiteral *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLocation());
ID.AddInteger(S->getKind());
ID.AddInteger(S->getValue());
}
@@ -329,6 +399,7 @@
void StmtProfiler::VisitFloatingLiteral(const FloatingLiteral *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLocation());
S->getValue().Profile(ID);
ID.AddBoolean(S->isExact());
}
@@ -339,6 +410,9 @@
void StmtProfiler::VisitStringLiteral(const StringLiteral *S) {
VisitExpr(S);
+ for (StringLiteral::tokloc_iterator I = S->tokloc_begin(),
+ E = S->tokloc_end(); I != E; ++I)
+ VisitSourceLocation(*I);
ID.AddString(S->getBytes());
ID.AddInteger(S->getKind());
}
@@ -345,22 +419,31 @@
void StmtProfiler::VisitParenExpr(const ParenExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLParen());
+ VisitSourceLocation(S->getRParen());
}
void StmtProfiler::VisitParenListExpr(const ParenListExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLParenLoc());
+ VisitSourceLocation(S->getRParenLoc());
}
void StmtProfiler::VisitUnaryOperator(const UnaryOperator *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getOperatorLoc());
ID.AddInteger(S->getOpcode());
}
void StmtProfiler::VisitOffsetOfExpr(const OffsetOfExpr *S) {
VisitType(S->getTypeSourceInfo()->getType());
+ VisitSourceLocation(S->getOperatorLoc());
+ VisitSourceLocation(S->getRParenLoc());
unsigned n = S->getNumComponents();
for (unsigned i = 0; i < n; ++i) {
- const OffsetOfExpr::OffsetOfNode& ON = S->getComponent(i);
+ const OffsetOfExpr::OffsetOfNode &ON = S->getComponent(i);
+ VisitSourceLocation(ON.getSourceRange().getBegin());
+ VisitSourceLocation(ON.getSourceRange().getEnd());
ID.AddInteger(ON.getKind());
switch (ON.getKind()) {
case OffsetOfExpr::OffsetOfNode::Array:
@@ -387,6 +470,8 @@
void
StmtProfiler::VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getOperatorLoc());
+ VisitSourceLocation(S->getRParenLoc());
ID.AddInteger(S->getKind());
if (S->isArgumentType())
VisitType(S->getArgumentType());
@@ -394,14 +479,17 @@
void StmtProfiler::VisitArraySubscriptExpr(const ArraySubscriptExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getRBracketLoc());
}
void StmtProfiler::VisitCallExpr(const CallExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getRParenLoc());
}
void StmtProfiler::VisitMemberExpr(const MemberExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getMemberLoc());
VisitDecl(S->getMemberDecl());
if (!Canonical)
VisitNestedNameSpecifier(S->getQualifier());
@@ -410,6 +498,7 @@
void StmtProfiler::VisitCompoundLiteralExpr(const CompoundLiteralExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLParenLoc());
ID.AddBoolean(S->isFileScope());
}
@@ -429,10 +518,13 @@
void StmtProfiler::VisitCStyleCastExpr(const CStyleCastExpr *S) {
VisitExplicitCastExpr(S);
+ VisitSourceLocation(S->getLParenLoc());
+ VisitSourceLocation(S->getRParenLoc());
}
void StmtProfiler::VisitBinaryOperator(const BinaryOperator *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getOperatorLoc());
ID.AddInteger(S->getOpcode());
}
@@ -443,24 +535,34 @@
void StmtProfiler::VisitConditionalOperator(const ConditionalOperator *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getQuestionLoc());
+ VisitSourceLocation(S->getColonLoc());
}
void StmtProfiler::VisitBinaryConditionalOperator(
const BinaryConditionalOperator *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getQuestionLoc());
+ VisitSourceLocation(S->getColonLoc());
}
void StmtProfiler::VisitAddrLabelExpr(const AddrLabelExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getAmpAmpLoc());
+ VisitSourceLocation(S->getLabelLoc());
VisitDecl(S->getLabel());
}
void StmtProfiler::VisitStmtExpr(const StmtExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLParenLoc());
+ VisitSourceLocation(S->getRParenLoc());
}
void StmtProfiler::VisitShuffleVectorExpr(const ShuffleVectorExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getBuiltinLoc());
+ VisitSourceLocation(S->getRParenLoc());
}
void StmtProfiler::VisitConvertVectorExpr(const ConvertVectorExpr *S) {
@@ -469,14 +571,19 @@
void StmtProfiler::VisitChooseExpr(const ChooseExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getBuiltinLoc());
+ VisitSourceLocation(S->getRParenLoc());
}
void StmtProfiler::VisitGNUNullExpr(const GNUNullExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getTokenLocation());
}
void StmtProfiler::VisitVAArgExpr(const VAArgExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getBuiltinLoc());
+ VisitSourceLocation(S->getRParenLoc());
}
void StmtProfiler::VisitInitListExpr(const InitListExpr *S) {
@@ -486,24 +593,32 @@
}
VisitExpr(S);
+ VisitSourceLocation(S->getLBraceLoc());
+ VisitSourceLocation(S->getRBraceLoc());
}
void StmtProfiler::VisitDesignatedInitExpr(const DesignatedInitExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getEqualOrColonLoc());
ID.AddBoolean(S->usesGNUSyntax());
for (DesignatedInitExpr::const_designators_iterator D =
S->designators_begin(), DEnd = S->designators_end();
D != DEnd; ++D) {
if (D->isFieldDesignator()) {
+ VisitSourceLocation(D->getDotLoc());
+ VisitSourceLocation(D->getFieldLoc());
ID.AddInteger(0);
VisitName(D->getFieldName());
continue;
}
+ VisitSourceLocation(D->getLBracketLoc());
+ VisitSourceLocation(D->getRBracketLoc());
if (D->isArrayDesignator()) {
ID.AddInteger(1);
} else {
assert(D->isArrayRangeDesignator());
+ VisitSourceLocation(D->getEllipsisLoc());
ID.AddInteger(2);
}
ID.AddInteger(D->getFirstExprIndex());
@@ -516,6 +631,7 @@
void StmtProfiler::VisitExtVectorElementExpr(const ExtVectorElementExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getAccessorLoc());
VisitName(&S->getAccessor());
}
@@ -526,6 +642,9 @@
void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getGenericLoc());
+ VisitSourceLocation(S->getDefaultLoc());
+ VisitSourceLocation(S->getRParenLoc());
for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
QualType T = S->getAssocType(i);
if (T.isNull())
@@ -547,6 +666,8 @@
void StmtProfiler::VisitAtomicExpr(const AtomicExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getBuiltinLoc());
+ VisitSourceLocation(S->getRParenLoc());
ID.AddInteger(S->getOp());
}
@@ -772,10 +893,14 @@
void StmtProfiler::VisitAsTypeExpr(const AsTypeExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getBuiltinLoc());
+ VisitSourceLocation(S->getRParenLoc());
}
void StmtProfiler::VisitCXXNamedCastExpr(const CXXNamedCastExpr *S) {
VisitExplicitCastExpr(S);
+ VisitSourceLocation(S->getOperatorLoc());
+ VisitSourceLocation(S->getRParenLoc());
}
void StmtProfiler::VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) {
@@ -797,15 +922,18 @@
void StmtProfiler::VisitUserDefinedLiteral(const UserDefinedLiteral *S) {
VisitCallExpr(S);
+ VisitSourceLocation(S->getUDSuffixLoc());
}
void StmtProfiler::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLocation());
ID.AddBoolean(S->getValue());
}
void StmtProfiler::VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLocation());
}
void StmtProfiler::VisitCXXStdInitializerListExpr(
@@ -815,6 +943,8 @@
void StmtProfiler::VisitCXXTypeidExpr(const CXXTypeidExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getSourceRange().getBegin());
+ VisitSourceLocation(S->getSourceRange().getEnd());
if (S->isTypeOperand())
VisitType(S->getTypeOperandSourceInfo()->getType());
}
@@ -821,6 +951,8 @@
void StmtProfiler::VisitCXXUuidofExpr(const CXXUuidofExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getSourceRange().getBegin());
+ VisitSourceLocation(S->getSourceRange().getEnd());
if (S->isTypeOperand())
VisitType(S->getTypeOperandSourceInfo()->getType());
}
@@ -832,15 +964,18 @@
void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLocation());
ID.AddBoolean(S->isImplicit());
}
void StmtProfiler::VisitCXXThrowExpr(const CXXThrowExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getThrowLoc());
}
void StmtProfiler::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getUsedLocation());
VisitDecl(S->getParam());
}
@@ -857,6 +992,9 @@
void StmtProfiler::VisitCXXConstructExpr(const CXXConstructExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLocation());
+ VisitSourceLocation(S->getParenOrBraceRange().getBegin());
+ VisitSourceLocation(S->getParenOrBraceRange().getEnd());
VisitDecl(S->getConstructor());
ID.AddBoolean(S->isElidable());
}
@@ -863,19 +1001,27 @@
void StmtProfiler::VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) {
VisitExplicitCastExpr(S);
+ VisitSourceLocation(S->getTypeInfoAsWritten()->getTypeLoc().getBeginLoc());
+ VisitSourceLocation(S->getRParenLoc());
}
void
StmtProfiler::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) {
VisitCXXConstructExpr(S);
+ VisitSourceLocation(S->getSourceRange().getBegin());
+ VisitSourceLocation(S->getSourceRange().getEnd());
}
void
StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getIntroducerRange().getBegin());
+ VisitSourceLocation(S->getIntroducerRange().getEnd());
for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
CEnd = S->explicit_capture_end();
C != CEnd; ++C) {
+ VisitSourceLocation(C->getLocation());
+ VisitSourceLocation(C->getEllipsisLoc());
ID.AddInteger(C->getCaptureKind());
switch (C->getCaptureKind()) {
case LCK_This:
@@ -896,10 +1042,12 @@
void
StmtProfiler::VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getRParenLoc());
}
void StmtProfiler::VisitCXXDeleteExpr(const CXXDeleteExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getSourceRange().getBegin());
ID.AddBoolean(S->isGlobalDelete());
ID.AddBoolean(S->isArrayForm());
VisitDecl(S->getOperatorDelete());
@@ -908,6 +1056,12 @@
void StmtProfiler::VisitCXXNewExpr(const CXXNewExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getTypeIdParens().getBegin());
+ VisitSourceLocation(S->getTypeIdParens().getEnd());
+ VisitSourceLocation(S->getStartLoc());
+ VisitSourceLocation(S->getEndLoc());
+ VisitSourceLocation(S->getDirectInitRange().getBegin());
+ VisitSourceLocation(S->getDirectInitRange().getEnd());
VisitType(S->getAllocatedType());
VisitDecl(S->getOperatorNew());
VisitDecl(S->getOperatorDelete());
@@ -921,6 +1075,10 @@
void
StmtProfiler::VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getOperatorLoc());
+ VisitSourceLocation(S->getColonColonLoc());
+ VisitSourceLocation(S->getTildeLoc());
+ VisitSourceLocation(S->getDestroyedTypeLoc());
ID.AddBoolean(S->isArrow());
VisitNestedNameSpecifier(S->getQualifier());
ID.AddBoolean(S->getScopeTypeInfo() != 0);
@@ -935,6 +1093,7 @@
void StmtProfiler::VisitOverloadExpr(const OverloadExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getNameLoc());
VisitNestedNameSpecifier(S->getQualifier());
VisitName(S->getName());
ID.AddBoolean(S->hasExplicitTemplateArgs());
@@ -950,6 +1109,8 @@
void StmtProfiler::VisitTypeTraitExpr(const TypeTraitExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getSourceRange().getBegin());
+ VisitSourceLocation(S->getSourceRange().getEnd());
ID.AddInteger(S->getTrait());
ID.AddInteger(S->getNumArgs());
for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I)
@@ -958,6 +1119,8 @@
void StmtProfiler::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getSourceRange().getBegin());
+ VisitSourceLocation(S->getSourceRange().getEnd());
ID.AddInteger(S->getTrait());
VisitType(S->getQueriedType());
}
@@ -964,6 +1127,8 @@
void StmtProfiler::VisitExpressionTraitExpr(const ExpressionTraitExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getSourceRange().getBegin());
+ VisitSourceLocation(S->getSourceRange().getEnd());
ID.AddInteger(S->getTrait());
VisitExpr(S->getQueriedExpression());
}
@@ -971,6 +1136,7 @@
void StmtProfiler::VisitDependentScopeDeclRefExpr(
const DependentScopeDeclRefExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLocation());
VisitName(S->getDeclName());
VisitNestedNameSpecifier(S->getQualifier());
ID.AddBoolean(S->hasExplicitTemplateArgs());
@@ -985,11 +1151,15 @@
void StmtProfiler::VisitCXXUnresolvedConstructExpr(
const CXXUnresolvedConstructExpr *S) {
VisitExpr(S);
+ VisitSourceLocation(S->getLParenLoc());
+ VisitSourceLocation(S->getRParenLoc());
VisitType(S->getTypeAsWritten());
}
void StmtProfiler::VisitCXXDependentScopeMemberExpr(
const CXXDependentScopeMemberExpr *S) {
+ VisitSourceLocation(S->getOperatorLoc());
+ VisitSourceLocation(S->getMemberLoc());
ID.AddBoolean(S->isImplicitAccess());
if (!S->isImplicitAccess()) {
VisitExpr(S);
@@ -1003,6 +1173,9 @@
}
void StmtProfiler::VisitUnresolvedMemberExpr(const UnresolvedMemberExpr *S) {
+ VisitSourceLocation(S->getOperatorLoc());
+ VisitSourceLocation(S->getMemberLoc());
+ /// XXX stopped here
ID.AddBoolean(S->isImplicitAccess());
if (!S->isImplicitAccess()) {
VisitExpr(S);
@@ -1056,6 +1229,7 @@
void StmtProfiler::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
VisitExpr(E);
+ VisitSourceLocation(E->getLocation());
}
void StmtProfiler::VisitObjCStringLiteral(const ObjCStringLiteral *S) {
@@ -1120,6 +1294,9 @@
VisitExpr(S);
VisitName(S->getSelector());
VisitDecl(S->getMethodDecl());
+ ID.AddInteger(S->getReceiverKind());
+ if (S->getReceiverKind() == ObjCMessageExpr::Class)
+ VisitType(S->getClassReceiver());
}
void StmtProfiler::VisitObjCIsaExpr(const ObjCIsaExpr *S) {
@@ -1263,7 +1440,7 @@
}
void Stmt::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
- bool Canonical) const {
- StmtProfiler Profiler(ID, Context, Canonical);
+ bool Canonical, bool Macro) const {
+ StmtProfiler Profiler(ID, Context, Canonical, Macro);
Profiler.Visit(this);
}
Index: lib/AST/TemplateBase.cpp
===================================================================
--- lib/AST/TemplateBase.cpp (revision 200870)
+++ lib/AST/TemplateBase.cpp (working copy)
@@ -275,7 +275,7 @@
break;
case Expression:
- getAsExpr()->Profile(ID, Context, true);
+ getAsExpr()->Profile(ID, Context, true, false);
break;
case Pack:
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp (revision 200870)
+++ lib/AST/Type.cpp (working copy)
@@ -141,7 +141,7 @@
ID.AddPointer(ET.getAsOpaquePtr());
ID.AddInteger(SizeMod);
ID.AddInteger(TypeQuals);
- E->Profile(ID, Context, true);
+ E->Profile(ID, Context, true, false);
}
DependentSizedExtVectorType::DependentSizedExtVectorType(const
@@ -165,7 +165,7 @@
const ASTContext &Context,
QualType ElementType, Expr *SizeExpr) {
ID.AddPointer(ElementType.getAsOpaquePtr());
- SizeExpr->Profile(ID, Context, true);
+ SizeExpr->Profile(ID, Context, true, false);
}
VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType,
@@ -1761,7 +1761,7 @@
for (unsigned i = 0; i != epi.NumExceptions; ++i)
ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr());
} else if (epi.ExceptionSpecType == EST_ComputedNoexcept && epi.NoexceptExpr){
- epi.NoexceptExpr->Profile(ID, Context, false);
+ epi.NoexceptExpr->Profile(ID, Context, false, false);
} else if (epi.ExceptionSpecType == EST_Uninstantiated ||
epi.ExceptionSpecType == EST_Unevaluated) {
ID.AddPointer(epi.ExceptionSpecDecl->getCanonicalDecl());
@@ -1805,7 +1805,7 @@
void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Context, Expr *E) {
- E->Profile(ID, Context, true);
+ E->Profile(ID, Context, true, false);
}
DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can)
@@ -1834,7 +1834,7 @@
void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Context, Expr *E) {
- E->Profile(ID, Context, true);
+ E->Profile(ID, Context, true, false);
}
TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp (revision 200870)
+++ lib/Sema/SemaChecking.cpp (working copy)
@@ -1576,10 +1576,10 @@
TheCall->setArg(i+1, Arg.take());
}
- ASTContext& Context = this->getASTContext();
+ ASTContext &Context = this->getASTContext();
// Create a new DeclRefExpr to refer to the new decl.
- DeclRefExpr* NewDRE = DeclRefExpr::Create(
+ DeclRefExpr *NewDRE = DeclRefExpr::Create(
Context,
DRE->getQualifierLoc(),
SourceLocation(),
@@ -3632,7 +3632,7 @@
/// \brief If E is a sizeof expression, returns its argument expression,
/// otherwise returns NULL.
-static const Expr *getSizeOfExprArg(const Expr* E) {
+static const Expr *getSizeOfExprArg(const Expr *E) {
if (const UnaryExprOrTypeTraitExpr *SizeOf =
dyn_cast<UnaryExprOrTypeTraitExpr>(E))
if (SizeOf->getKind() == clang::UETT_SizeOf && !SizeOf->isArgumentType())
@@ -3706,9 +3706,9 @@
// We only compute IDs for expressions if the warning is enabled, and
// cache the sizeof arg's ID.
if (SizeOfArgID == llvm::FoldingSetNodeID())
- SizeOfArg->Profile(SizeOfArgID, Context, true);
+ SizeOfArg->Profile(SizeOfArgID, Context, true, false);
llvm::FoldingSetNodeID DestID;
- Dest->Profile(DestID, Context, true);
+ Dest->Profile(DestID, Context, true, false);
if (DestID == SizeOfArgID) {
// TODO: For strncpy() and friends, this could suggest sizeof(dst)
// over sizeof(src) as well.
@@ -3818,7 +3818,7 @@
Ex = Ex->IgnoreParenCasts();
for (;;) {
- const BinaryOperator * BO = dyn_cast<BinaryOperator>(Ex);
+ const BinaryOperator *BO = dyn_cast<BinaryOperator>(Ex);
if (!BO || !BO->isAdditiveOp())
break;
@@ -5630,6 +5630,18 @@
SourceLocation CC, QualType T) {
AnalyzeImplicitConversions(S, E->getCond(), CC);
+ if (S.ActiveTemplateInstantiations.empty()) {
+ SmallVector<Stmt*, 2> Exprs;
+ Exprs.push_back(E->getTrueExpr());
+ ConditionalOperator *CO =
+ dyn_cast<ConditionalOperator>(E->getFalseExpr());
+ if (CO && !CO->getCond()->HasSideEffects(S.getASTContext()))
+ Exprs.push_back(CO->getTrueExpr());
+ else
+ Exprs.push_back(E->getFalseExpr());
+ S.CheckStatementsUnique(E->getColonLoc(), Exprs);
+ }
+
bool Suspicious = false;
CheckConditionalOperand(S, E->getTrueExpr(), T, CC, Suspicious);
CheckConditionalOperand(S, E->getFalseExpr(), T, CC, Suspicious);
@@ -7356,6 +7368,7 @@
}
}
}
+} // unnamed namespace
/// \brief Retrieve the C type corresponding to type tag TypeExpr.
///
@@ -7369,7 +7382,7 @@
/// \param TypeInfo Information about the corresponding C type.
///
/// \returns true if the corresponding C type was found.
-bool GetMatchingCType(
+static bool GetMatchingCType(
const IdentifierInfo *ArgumentKind,
const Expr *TypeExpr, const ASTContext &Ctx,
const llvm::DenseMap<Sema::TypeTagMagicValue,
@@ -7415,7 +7428,6 @@
TypeInfo = I->second;
return true;
}
-} // unnamed namespace
void Sema::RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind,
uint64_t MagicValue, QualType Type,
@@ -7430,8 +7442,7 @@
TypeTagData(Type, LayoutCompatible, MustBeNull);
}
-namespace {
-bool IsSameCharType(QualType T1, QualType T2) {
+static bool IsSameCharType(QualType T1, QualType T2) {
const BuiltinType *BT1 = T1->getAs<BuiltinType>();
if (!BT1)
return false;
@@ -7448,7 +7459,6 @@
(T1Kind == BuiltinType::Char_U && T2Kind == BuiltinType::UChar) ||
(T1Kind == BuiltinType::Char_S && T2Kind == BuiltinType::SChar);
}
-} // unnamed namespace
void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
const Expr * const *ExprArgs) {
@@ -7528,3 +7538,64 @@
<< ArgumentExpr->getSourceRange()
<< TypeTagExpr->getSourceRange();
}
+
+static SourceLocation GetFirstLineLoc(Stmt *S) {
+ if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
+ CompoundStmt::body_iterator I = CS->body_begin(), E = CS->body_end();
+ while (I != E && *I == NULL)
+ ++I;
+ if (I == E)
+ // A compound statement with no non-NULL statements inside it. Could
+ // be { }. Point to the leading '{'.
+ return CS->getLocStart();
+ return GetFirstLineLoc(*I);
+ }
+
+ return S->getLocStart();
+}
+
+/// Verify that all of the statements in the list are unique. The statements
+/// should be given in source order in order to provide diagnostics the right
+/// way around.
+void Sema::CheckStatementsUnique(SourceLocation Loc, ArrayRef<Stmt*> Stmts) {
+ llvm::DenseMap<unsigned, unsigned> Profiles;
+ for (int i = 0, e = Stmts.size(); i != e; ++i) {
+ llvm::FoldingSetNodeID ProfileID;
+ Stmts[i]->Profile(ProfileID, Context, true, true);
+ unsigned ProfileHash = ProfileID.ComputeHash();
+ if (!Profiles.insert(std::make_pair(ProfileHash, i)).second) {
+ unsigned j = Profiles[ProfileHash];
+ SourceManager &SM = PP.getSourceManager();
+ FullSourceLoc First = FullSourceLoc(GetFirstLineLoc(Stmts[j]), SM);
+ FullSourceLoc Second = FullSourceLoc(GetFirstLineLoc(Stmts[i]), SM);
+ FullSourceLoc FullLoc = FullSourceLoc(Loc, SM);
+ bool FirstSameLine = First.getFileID() == FullLoc.getFileID() &&
+ First.getSpellingLineNumber() == FullLoc.getSpellingLineNumber();
+ bool SecondSameLine = Second.getFileID() == FullLoc.getFileID() &&
+ Second.getSpellingLineNumber() == FullLoc.getSpellingLineNumber();
+
+ if (FirstSameLine && SecondSameLine) {
+ Diag(Loc, diag::warn_condition_same_stmt)
+ << (isa<Expr>(Stmts[i]) && isa<Expr>(Stmts[j]))
+ << Stmts[j]->getSourceRange()
+ << Stmts[i]->getSourceRange();
+ } else if (FirstSameLine) {
+ Diag(Loc, diag::warn_condition_same_stmt)
+ << (isa<Expr>(Stmts[i]) && isa<Expr>(Stmts[j]))
+ << Stmts[j]->getSourceRange();
+ Diag(Second, diag::note_code_here) << (isa<Expr>(Stmts[i]));
+ } else if (SecondSameLine) {
+ Diag(Loc, diag::warn_condition_same_stmt)
+ << (isa<Expr>(Stmts[i]) && isa<Expr>(Stmts[j]))
+ << Stmts[i]->getSourceRange();
+ Diag(First, diag::note_code_here) << (isa<Expr>(Stmts[j]));
+ } else {
+ Diag(Loc, diag::warn_condition_same_stmt)
+ << (isa<Expr>(Stmts[i]) && isa<Expr>(Stmts[j]));
+ Diag(First, diag::note_code_here) << (isa<Expr>(Stmts[j]));
+ Diag(Second, diag::note_code_here) << (isa<Expr>(Stmts[i]));
+ }
+ }
+ }
+}
+
Index: lib/Sema/SemaOverload.cpp
===================================================================
--- lib/Sema/SemaOverload.cpp (revision 200870)
+++ lib/Sema/SemaOverload.cpp (working copy)
@@ -1086,8 +1086,8 @@
if (NewI == NewE || OldI == OldE)
return true;
llvm::FoldingSetNodeID NewID, OldID;
- NewI->getCond()->Profile(NewID, Context, true);
- OldI->getCond()->Profile(OldID, Context, true);
+ NewI->getCond()->Profile(NewID, Context, true, false);
+ OldI->getCond()->Profile(OldID, Context, true, false);
if (NewID != OldID)
return true;
}
@@ -8276,9 +8276,11 @@
return true;
llvm::FoldingSetNodeID Cand1ID, Cand2ID;
cast<EnableIfAttr>(*Cand1I)->getCond()->Profile(Cand1ID,
- S.getASTContext(), true);
+ S.getASTContext(),
+ true, false);
cast<EnableIfAttr>(*Cand2I)->getCond()->Profile(Cand2ID,
- S.getASTContext(), true);
+ S.getASTContext(),
+ true, false);
if (Cand1ID != Cand2ID)
return false;
}
Index: lib/Sema/SemaStmt.cpp
===================================================================
--- lib/Sema/SemaStmt.cpp (revision 200870)
+++ lib/Sema/SemaStmt.cpp (working copy)
@@ -458,6 +458,17 @@
DiagnoseUnusedExprResult(elseStmt);
+ if (ActiveTemplateInstantiations.empty() && elseStmt) {
+ SmallVector<Stmt*, 2> Exprs;
+ Exprs.push_back(thenStmt);
+ IfStmt *elseIfStmt = dyn_cast<IfStmt>(elseStmt);
+ if (elseIfStmt && !elseIfStmt->getCond()->HasSideEffects(Context))
+ Exprs.push_back(elseIfStmt->getThen());
+ else
+ Exprs.push_back(elseStmt);
+ CheckStatementsUnique(ElseLoc, Exprs);
+ }
+
return Owned(new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr,
thenStmt, ElseLoc, elseStmt));
}
Index: lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- lib/Sema/SemaTemplateDeduction.cpp (revision 200870)
+++ lib/Sema/SemaTemplateDeduction.cpp (working copy)
@@ -239,8 +239,8 @@
if (Y.getKind() == TemplateArgument::Expression) {
// Compare the expressions for equality
llvm::FoldingSetNodeID ID1, ID2;
- X.getAsExpr()->Profile(ID1, Context, true);
- Y.getAsExpr()->Profile(ID2, Context, true);
+ X.getAsExpr()->Profile(ID1, Context, true, false);
+ Y.getAsExpr()->Profile(ID2, Context, true, false);
if (ID1 == ID2)
return X;
}
@@ -1970,8 +1970,8 @@
case TemplateArgument::Expression: {
llvm::FoldingSetNodeID XID, YID;
- X.getAsExpr()->Profile(XID, Context, true);
- Y.getAsExpr()->Profile(YID, Context, true);
+ X.getAsExpr()->Profile(XID, Context, true, false);
+ Y.getAsExpr()->Profile(YID, Context, true, false);
return XID == YID;
}
Index: test/Analysis/additive-folding-range-constraints.c
===================================================================
--- test/Analysis/additive-folding-range-constraints.c (revision 200870)
+++ test/Analysis/additive-folding-range-constraints.c (working copy)
@@ -117,11 +117,11 @@
clang_analyzer_eval((a + 5) == 0LL); // expected-warning{{UNKNOWN}}
if ((a + 5) == 0LL) {
- clang_analyzer_eval(a == 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(a == 0); // expected-warning{{FALSE}} // expected-note{{in statement here}}
clang_analyzer_eval(a == 0x7F); // expected-warning{{FALSE}}
clang_analyzer_eval(a == -0x80); // expected-warning{{FALSE}}
- } else {
- clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}}
+ } else { // expected-warning{{same statements on either side of condition}}
+ clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}} // expected-note{{in statement here}}
clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}}
clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}}
}
Index: test/Analysis/identical-expressions.cpp
===================================================================
--- test/Analysis/identical-expressions.cpp (revision 200870)
+++ test/Analysis/identical-expressions.cpp (working copy)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core.IdenticalExpr -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core.IdenticalExpr -verify -Wno-useless-condition %s
/* Only one expected warning per function allowed at the very end. */
Index: test/Analysis/inlining/test-always-inline-size-option.c
===================================================================
--- test/Analysis/inlining/test-always-inline-size-option.c (revision 200870)
+++ test/Analysis/inlining/test-always-inline-size-option.c (working copy)
@@ -4,9 +4,10 @@
int nested5() {
if (5 < 3)
return 0;
- else
+ else {
if (3 == 3)
return 0;
+ }
return 0;
}
int nested4() {
Index: test/Analysis/malloc-interprocedural.c
===================================================================
--- test/Analysis/malloc-interprocedural.c (revision 200870)
+++ test/Analysis/malloc-interprocedural.c (working copy)
@@ -121,15 +121,15 @@
return result;
}
-void useStrndup(size_t n) {
+int useStrndup(size_t n) {
if (n == 0) {
(void)strndup(0, 20); // no-warning
- return;
+ return 0;
} else if (n < 5) {
(void)strndup("hi there", n); // no-warning
- return;
+ return 1;
} else {
(void)strndup("hi there", n);
- return; // expected-warning{{leak}}
+ return 2; // expected-warning{{leak}}
}
}
Index: test/Analysis/malloc.c
===================================================================
--- test/Analysis/malloc.c (revision 200870)
+++ test/Analysis/malloc.c (working copy)
@@ -416,9 +416,9 @@
void mallocFailedOrNot() {
int *p = malloc(12);
if (!p)
- free(p);
- else
- free(p);
+ free(p); // expected-note{{in expression here}}
+ else // expected-warning{{same expressions on either side of condition}}
+ free(p); // expected-note{{in expression here}}
}
struct StructWithInt {
@@ -446,12 +446,12 @@
return; // no warning
}
-void mallocFailedOrNotLeak() {
+int mallocFailedOrNotLeak() {
int *p = malloc(12);
if (p == 0)
- return; // no warning
+ return 0; // no warning
else
- return; // expected-warning {{Potential leak of memory pointed to by}}
+ return 1; // expected-warning {{Potential leak of memory pointed to by}}
}
void mallocAssignment() {
@@ -813,7 +813,7 @@
free(buffer);
}
-void radar10978247_positive(int myValueSize) {
+int radar10978247_positive(int myValueSize) {
char stackBuffer[128];
char *buffer;
@@ -824,10 +824,11 @@
// do stuff with the buffer
if (buffer == stackBuffer)
- return;
+ return 0;
else
- return; // expected-warning {{leak}}
-}
+ return 1; // expected-warning {{leak}}
+}
+
// <rdar://problem/11269741> Previously this triggered a false positive
// because malloc() is known to return uninitialized memory and the binding
// of 'o' to 'p->n' was not getting propertly handled. Now we report a leak.
Index: test/Analysis/misc-ps-region-store.cpp
===================================================================
--- test/Analysis/misc-ps-region-store.cpp (revision 200870)
+++ test/Analysis/misc-ps-region-store.cpp (working copy)
@@ -584,13 +584,15 @@
}
// Test handling CXXScalarValueInitExprs.
-void rdar11401827() {
+int rdar11401827() {
int x = int();
if (!x) {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+ return 0;
}
else {
clang_analyzer_warnIfReached(); // no-warning
+ return 1;
}
}
Index: test/Analysis/operator-calls.cpp
===================================================================
--- test/Analysis/operator-calls.cpp (revision 200870)
+++ test/Analysis/operator-calls.cpp (working copy)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify %s
+// RUN: %clang_cc1 -std=c++11 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -Wno-useless-condition %s
void clang_analyzer_eval(bool);
struct X0 { };
Index: test/Analysis/retain-release.m
===================================================================
--- test/Analysis/retain-release.m (revision 200870)
+++ test/Analysis/retain-release.m (working copy)
@@ -1893,9 +1893,9 @@
@autoreleasepool {
NSString *printString;
if(y > 2)
- printString = [[NSString alloc] init];
- else
- printString = [[NSString alloc] init];
+ printString = [[NSString alloc] init]; // expected-note {{in expression here}}
+ else // expected-warning {{same expressions on either side of condition}}
+ printString = [[NSString alloc] init]; // expected-note {{in expression here}}
NSLog(@"Once %@", printString);
[printString release];
NSLog(@"Again: %@", printString); // expected-warning {{Reference-counted object is used after it is released}}
Index: test/Analysis/weak-functions.c
===================================================================
--- test/Analysis/weak-functions.c (revision 200870)
+++ test/Analysis/weak-functions.c (working copy)
@@ -4,35 +4,41 @@
void myFunc();
void myWeakFunc() __attribute__((weak_import));
-void testWeakFuncIsNull()
+int testWeakFuncIsNull()
{
clang_analyzer_eval(myFunc == NULL); // expected-warning{{FALSE}}
clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{UNKNOWN}}
if (myWeakFunc == NULL) {
clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{TRUE}}
+ return 0;
} else {
clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{FALSE}}
+ return 1;
}
}
-void testWeakFuncIsNot()
+int testWeakFuncIsNot()
{
clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{UNKNOWN}}
if (!myWeakFunc) {
clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{TRUE}}
+ return 0;
} else {
clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{FALSE}}
+ return 1;
}
}
-void testWeakFuncIsTrue()
+int testWeakFuncIsTrue()
{
- clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{UNKNOWN}}
- if (myWeakFunc) {
- clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{FALSE}}
- } else {
- clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{TRUE}}
- }
+ clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{UNKNOWN}}
+ if (myWeakFunc) {
+ clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{FALSE}}
+ return 0;
+ } else {
+ clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{TRUE}}
+ return 1;
+ }
}
//===----------------------------------------------------------------------===
Index: test/SemaCXX/warn-useless-condition.cpp
===================================================================
--- test/SemaCXX/warn-useless-condition.cpp (revision 0)
+++ test/SemaCXX/warn-useless-condition.cpp (working copy)
@@ -0,0 +1,112 @@
+// RUN: %clang_cc1 -Wuseless-condition -verify %s
+
+extern int code();
+
+void test1(int expr) {
+ if (expr) {
+ code(); // expected-note{{in statement here}}
+ } else { // expected-warning{{same statements on either side of condition}}
+ code(); // expected-note{{in statement here}}
+ }
+}
+
+int test2(int expr) {
+ return expr ? code() : code(); // expected-warning{{same expressions on either side of condition}}
+}
+
+void test3(int expr, int expr2) {
+ // We don't want to warn on this. expr2 may be long and complicated and we
+ // shouldn't force people to repeat " && !expr2" in each condition leading
+ // up to that block.
+ if (expr) {
+ code();
+ } else if (expr2) {
+ return;
+ } else {
+ code();
+ }
+}
+
+int test4(int expr, int expr2) {
+ // It's conservative, but we don't want to warn on this either. Treating if
+ // and ?: differently is too close to being a style issue.
+ return expr ? (expr2 ? code() : 0) : code();
+}
+
+void test5(int expr) {
+ if (expr) {
+ code();
+ } else if (code()) {
+ code(); // expected-note{{in statement here}}
+ } else { // expected-warning{{same statements on either side of condition}}
+ code(); // expected-note{{in statement here}}
+ }
+}
+
+int test6(int x, int y, int z) {
+ if (x) {
+ return 0;
+ } else if (y) {
+ return 1;
+ } else if (z) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+struct true_type {
+ static const bool value = true;
+ operator bool() { return value; }
+};
+struct false_type {
+ static const bool value = false;
+ operator bool() { return value; }
+};
+template <typename T> struct is_pointer : false_type {};
+template <typename T> struct is_pointer<T*> : true_type {};
+template <typename T, typename U> struct is_same : public false_type {};
+template <typename T> struct is_same<T, T> : public true_type {};
+
+template <typename T>
+int test7_util(int expr) {
+ if (expr)
+ return is_pointer<T>::value;
+ else
+ return is_same<T, T>::value;
+}
+
+int test7(int expr) {
+ return test7_util<int*>(expr);
+}
+
+#define num_cpus() (1)
+#define max_omp_threads() (1)
+
+int test8(int expr) {
+ if (expr) {
+ return num_cpus();
+ } else {
+ return max_omp_threads();
+ }
+}
+
+int test9(int expr) {
+ if (expr) {
+ return num_cpus(); // expected-note{{in statement here}}
+ } else { // expected-warning{{same statements on either side of condition}}
+ return num_cpus(); // expected-note{{in statement here}}
+ }
+}
+
+/* This is a false positive.
+#define BLANK
+
+int test10(int x, int expr) {
+ if (expr) {
+ return x > -5;
+ } else {
+ return x > BLANK - 5;
+ }
+}
+*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment