summaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2012-08-19 10:33:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2012-08-19 10:33:04 +0000
commit657bc3d9848e3be92029b2416031340988cd0111 (patch)
tree5b9c2fa9d79942fbdce3d618e37e27c18263af9a /include/clang
parent56d91b49b13fe55c918afbda19f6165b5fbff87a (diff)
Notes
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/AST/ASTContext.h20
-rw-r--r--include/clang/AST/Attr.h3
-rw-r--r--include/clang/AST/CommentCommandTraits.h6
-rw-r--r--include/clang/AST/DeclBase.h4
-rw-r--r--include/clang/AST/DeclCXX.h13
-rw-r--r--include/clang/AST/DeclGroup.h6
-rw-r--r--include/clang/AST/DeclLookups.h4
-rw-r--r--include/clang/AST/PrettyPrinter.h26
-rw-r--r--include/clang/AST/RawCommentList.h30
-rw-r--r--include/clang/AST/Stmt.h32
-rw-r--r--include/clang/AST/TemplateBase.h20
-rw-r--r--include/clang/AST/TypeLoc.h9
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h148
-rw-r--r--include/clang/Basic/Attr.td21
-rw-r--r--include/clang/Basic/Builtins.def6
-rw-r--r--include/clang/Basic/DiagnosticGroups.td8
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td4
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td36
-rw-r--r--include/clang/Lex/PTHManager.h2
-rw-r--r--include/clang/Parse/Parser.h4
-rw-r--r--include/clang/Sema/AttributeList.h107
-rw-r--r--include/clang/Sema/Sema.h43
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h51
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h22
-rw-r--r--include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h30
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h27
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h12
29 files changed, 542 insertions, 162 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 8fd7d6ef42330..cad3ad2b5f9c3 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -474,8 +474,17 @@ public:
Data.setPointer(RC);
}
+ const Decl *getOriginalDecl() const LLVM_READONLY {
+ return OriginalDecl;
+ }
+
+ void setOriginalDecl(const Decl *Orig) {
+ OriginalDecl = Orig;
+ }
+
private:
llvm::PointerIntPair<const RawComment *, 2, Kind> Data;
+ const Decl *OriginalDecl;
};
/// \brief Mapping from declarations to comments attached to any
@@ -485,6 +494,10 @@ public:
/// lazily.
mutable llvm::DenseMap<const Decl *, RawCommentAndCacheFlags> RedeclComments;
+ /// \brief Mapping from declarations to parsed comments attached to any
+ /// redeclaration.
+ mutable llvm::DenseMap<const Decl *, comments::FullComment *> ParsedComments;
+
/// \brief Return the documentation comment attached to a given declaration,
/// without looking into cache.
RawComment *getRawCommentForDeclNoCache(const Decl *D) const;
@@ -500,7 +513,12 @@ public:
/// \brief Return the documentation comment attached to a given declaration.
/// Returns NULL if no comment is attached.
- const RawComment *getRawCommentForAnyRedecl(const Decl *D) const;
+ ///
+ /// \param OriginalDecl if not NULL, is set to declaration AST node that had
+ /// the comment, if the comment we found comes from a redeclaration.
+ const RawComment *getRawCommentForAnyRedecl(
+ const Decl *D,
+ const Decl **OriginalDecl = NULL) const;
/// Return parsed documentation comment attached to a given declaration.
/// Returns NULL if no comment is attached.
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 27b44d4bd97b0..b17bd48b7d03c 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -105,7 +105,8 @@ public:
virtual bool isLateParsed() const { return false; }
// Pretty print this attribute.
- virtual void printPretty(llvm::raw_ostream &OS, ASTContext &C) const = 0;
+ virtual void printPretty(llvm::raw_ostream &OS,
+ const PrintingPolicy &Policy) const = 0;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *) { return true; }
diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h
index f1883755e5202..5f0269a4650b1 100644
--- a/include/clang/AST/CommentCommandTraits.h
+++ b/include/clang/AST/CommentCommandTraits.h
@@ -35,14 +35,14 @@ public:
/// A verbatim-like block command eats every character (except line starting
/// decorations) until matching end command is seen or comment end is hit.
///
- /// \param BeginName name of the command that starts the verbatim block.
+ /// \param StartName name of the command that starts the verbatim block.
/// \param [out] EndName name of the command that ends the verbatim block.
///
/// \returns true if a given command is a verbatim block command.
bool isVerbatimBlockCommand(StringRef StartName, StringRef &EndName) const;
/// \brief Register a new verbatim block command.
- void addVerbatimBlockCommand(StringRef BeginName, StringRef EndName);
+ void addVerbatimBlockCommand(StringRef StartName, StringRef EndName);
/// \brief Check if a given command is a verbatim line command.
///
@@ -90,7 +90,7 @@ public:
private:
struct VerbatimBlockCommand {
- StringRef BeginName;
+ StringRef StartName;
StringRef EndName;
};
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index ac2cc9ec4d271..0f596095f74a2 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -858,10 +858,10 @@ public:
raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0);
// Debuggers don't usually respect default arguments.
- LLVM_ATTRIBUTE_USED void dump() const { dump(llvm::errs()); }
+ LLVM_ATTRIBUTE_USED void dump() const;
void dump(raw_ostream &Out) const;
// Debuggers don't usually respect default arguments.
- LLVM_ATTRIBUTE_USED void dumpXML() const { dumpXML(llvm::errs()); }
+ LLVM_ATTRIBUTE_USED void dumpXML() const;
void dumpXML(raw_ostream &OS) const;
private:
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 851e3105bc0df..2d95f038dfd47 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -1646,14 +1646,17 @@ public:
/// \brief Find the method in RD that corresponds to this one.
///
/// Find if RD or one of the classes it inherits from override this method.
- /// If so, return it. RD is assumed to be a base class of the class defining
- /// this method (or be the class itself).
+ /// If so, return it. RD is assumed to be a subclass of the class defining
+ /// this method (or be the class itself), unless MayBeBase is set to true.
CXXMethodDecl *
- getCorrespondingMethodInClass(const CXXRecordDecl *RD);
+ getCorrespondingMethodInClass(const CXXRecordDecl *RD,
+ bool MayBeBase = false);
const CXXMethodDecl *
- getCorrespondingMethodInClass(const CXXRecordDecl *RD) const {
- return const_cast<CXXMethodDecl*>(this)->getCorrespondingMethodInClass(RD);
+ getCorrespondingMethodInClass(const CXXRecordDecl *RD,
+ bool MayBeBase = false) const {
+ return const_cast<CXXMethodDecl *>(this)
+ ->getCorrespondingMethodInClass(RD, MayBeBase);
}
// Implement isa/cast/dyncast/etc.
diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h
index 63cdac594920a..cda6ae520af4e 100644
--- a/include/clang/AST/DeclGroup.h
+++ b/include/clang/AST/DeclGroup.h
@@ -26,7 +26,11 @@ class DeclGroupIterator;
class DeclGroup {
// FIXME: Include a TypeSpecifier object.
- unsigned NumDecls;
+ union {
+ unsigned NumDecls;
+
+ Decl *Aligner;
+ };
private:
DeclGroup() : NumDecls(0) {}
diff --git a/include/clang/AST/DeclLookups.h b/include/clang/AST/DeclLookups.h
index b8abe97be1fbc..867b465257533 100644
--- a/include/clang/AST/DeclLookups.h
+++ b/include/clang/AST/DeclLookups.h
@@ -67,7 +67,7 @@ public:
DeclContext::all_lookups_iterator DeclContext::lookups_begin() const {
DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
- if (hasExternalVisibleStorage())
+ if (Primary->hasExternalVisibleStorage())
getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary);
if (StoredDeclsMap *Map = Primary->buildLookup())
return all_lookups_iterator(Map->begin(), Map->end());
@@ -76,7 +76,7 @@ DeclContext::all_lookups_iterator DeclContext::lookups_begin() const {
DeclContext::all_lookups_iterator DeclContext::lookups_end() const {
DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
- if (hasExternalVisibleStorage())
+ if (Primary->hasExternalVisibleStorage())
getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary);
if (StoredDeclsMap *Map = Primary->buildLookup())
return all_lookups_iterator(Map->end(), Map->end());
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
index 2e34dc8cbd5c3..f2c015fffe946 100644
--- a/include/clang/AST/PrettyPrinter.h
+++ b/include/clang/AST/PrettyPrinter.h
@@ -34,19 +34,19 @@ public:
struct PrintingPolicy {
/// \brief Create a default printing policy for C.
PrintingPolicy(const LangOptions &LO)
- : Indentation(2), LangOpts(LO), SuppressSpecifiers(false),
+ : LangOpts(LO), Indentation(2), SuppressSpecifiers(false),
SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false),
SuppressUnwrittenScope(false), SuppressInitializers(false),
- Dump(false), ConstantArraySizeAsWritten(false),
- AnonymousTagLocations(true), SuppressStrongLifetime(false),
- Bool(LO.Bool) { }
-
- /// \brief The number of spaces to use to indent each line.
- unsigned Indentation : 8;
+ ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
+ SuppressStrongLifetime(false), Bool(LO.Bool),
+ DumpSourceManager(0) { }
/// \brief What language we're printing.
LangOptions LangOpts;
+ /// \brief The number of spaces to use to indent each line.
+ unsigned Indentation : 8;
+
/// \brief Whether we should suppress printing of the actual specifiers for
/// the given type or declaration.
///
@@ -103,12 +103,6 @@ struct PrintingPolicy {
/// internal initializer constructed for x will not be printed.
bool SuppressInitializers : 1;
- /// \brief True when we are "dumping" rather than "pretty-printing",
- /// where dumping involves printing the internal details of the AST
- /// and pretty-printing involves printing something similar to
- /// source code.
- bool Dump : 1;
-
/// \brief Whether we should print the sizes of constant array expressions
/// as written in the sources.
///
@@ -139,6 +133,12 @@ struct PrintingPolicy {
/// \brief Whether we can use 'bool' rather than '_Bool', even if the language
/// doesn't actually have 'bool' (because, e.g., it is defined as a macro).
unsigned Bool : 1;
+
+ /// \brief If we are "dumping" rather than "pretty-printing", this points to
+ /// a SourceManager which will be used to dump SourceLocations. Dumping
+ /// involves printing the internal details of the AST and pretty-printing
+ /// involves printing something similar to source code.
+ SourceManager *DumpSourceManager;
};
} // end namespace clang
diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h
index 4901d07c3cdc9..630626b438ee5 100644
--- a/include/clang/AST/RawCommentList.h
+++ b/include/clang/AST/RawCommentList.h
@@ -55,16 +55,11 @@ public:
/// Is this comment attached to any declaration?
bool isAttached() const LLVM_READONLY {
- return !DeclOrParsedComment.isNull();
+ return IsAttached;
}
- /// Return the declaration that this comment is attached to.
- const Decl *getDecl() const;
-
- /// Set the declaration that this comment is attached to.
- void setDecl(const Decl *D) {
- assert(DeclOrParsedComment.isNull());
- DeclOrParsedComment = D;
+ void setAttached() {
+ IsAttached = true;
}
/// Returns true if it is a comment that should be put after a member:
@@ -118,28 +113,23 @@ public:
return extractBriefText(Context);
}
- /// Returns a \c FullComment AST node, parsing the comment if needed.
- comments::FullComment *getParsed(const ASTContext &Context) const {
- if (comments::FullComment *FC =
- DeclOrParsedComment.dyn_cast<comments::FullComment *>())
- return FC;
-
- return parse(Context);
- }
+ /// Parse the comment, assuming it is attached to decl \c D.
+ comments::FullComment *parse(const ASTContext &Context, const Decl *D) const;
private:
SourceRange Range;
mutable StringRef RawText;
mutable const char *BriefText;
- mutable llvm::PointerUnion<const Decl *, comments::FullComment *>
- DeclOrParsedComment;
mutable bool RawTextValid : 1; ///< True if RawText is valid
mutable bool BriefTextValid : 1; ///< True if BriefText is valid
unsigned Kind : 3;
+ /// True if comment is attached to a declaration in ASTContext.
+ bool IsAttached : 1;
+
bool IsTrailingComment : 1;
bool IsAlmostTrailingComment : 1;
@@ -152,7 +142,7 @@ private:
RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment,
bool IsAlmostTrailingComment) :
Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K),
- IsTrailingComment(IsTrailingComment),
+ IsAttached(false), IsTrailingComment(IsTrailingComment),
IsAlmostTrailingComment(IsAlmostTrailingComment),
BeginLineValid(false), EndLineValid(false)
{ }
@@ -161,8 +151,6 @@ private:
const char *extractBriefText(const ASTContext &Context) const;
- comments::FullComment *parse(const ASTContext &Context) const;
-
friend class ASTReader;
};
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 79e1920159cd7..35fb69312b6e9 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -373,15 +373,9 @@ public:
/// dumpPretty/printPretty - These two methods do a "pretty print" of the AST
/// back to its original source language syntax.
- void dumpPretty(ASTContext& Context) const;
+ void dumpPretty(ASTContext &Context) const;
void printPretty(raw_ostream &OS, PrinterHelper *Helper,
const PrintingPolicy &Policy,
- unsigned Indentation = 0) const {
- printPretty(OS, *(ASTContext*)0, Helper, Policy, Indentation);
- }
- void printPretty(raw_ostream &OS, ASTContext &Context,
- PrinterHelper *Helper,
- const PrintingPolicy &Policy,
unsigned Indentation = 0) const;
/// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only
@@ -1620,36 +1614,40 @@ public:
/// MSAsmStmt - This represents a MS inline-assembly statement extension.
///
class MSAsmStmt : public Stmt {
- SourceLocation AsmLoc, EndLoc;
+ SourceLocation AsmLoc, LBraceLoc, EndLoc;
std::string AsmStr;
bool IsSimple;
bool IsVolatile;
unsigned NumAsmToks;
- unsigned NumLineEnds;
+ unsigned NumInputs;
+ unsigned NumOutputs;
unsigned NumClobbers;
Token *AsmToks;
- unsigned *LineEnds;
+ IdentifierInfo **Names;
Stmt **Exprs;
StringRef *Clobbers;
public:
- MSAsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple,
- bool isvolatile, ArrayRef<Token> asmtoks,
- ArrayRef<unsigned> lineends, StringRef asmstr,
- ArrayRef<StringRef> clobbers, SourceLocation endloc);
+ MSAsmStmt(ASTContext &C, SourceLocation asmloc, SourceLocation lbraceloc,
+ bool issimple, bool isvolatile, ArrayRef<Token> asmtoks,
+ ArrayRef<IdentifierInfo*> inputs, ArrayRef<IdentifierInfo*> outputs,
+ StringRef asmstr, ArrayRef<StringRef> clobbers,
+ SourceLocation endloc);
SourceLocation getAsmLoc() const { return AsmLoc; }
void setAsmLoc(SourceLocation L) { AsmLoc = L; }
+ SourceLocation getLBraceLoc() const { return LBraceLoc; }
+ void setLBraceLoc(SourceLocation L) { LBraceLoc = L; }
SourceLocation getEndLoc() const { return EndLoc; }
void setEndLoc(SourceLocation L) { EndLoc = L; }
+ bool hasBraces() const { return LBraceLoc.isValid(); }
+
unsigned getNumAsmToks() { return NumAsmToks; }
Token *getAsmToks() { return AsmToks; }
- unsigned getNumLineEnds() { return NumLineEnds; }
- unsigned *getLineEnds() { return LineEnds; }
bool isVolatile() const { return IsVolatile; }
void setVolatile(bool V) { IsVolatile = V; }
@@ -1665,7 +1663,7 @@ public:
//===--- Other ---===//
unsigned getNumClobbers() const { return NumClobbers; }
- StringRef getClobber(unsigned i) { return Clobbers[i]; }
+ StringRef getClobber(unsigned i) const { return Clobbers[i]; }
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(AsmLoc, EndLoc);
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 54c9f2c534d2c..5047028e5eac4 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -510,17 +510,23 @@ public:
/// This is safe to be used inside an AST node, in contrast with
/// TemplateArgumentListInfo.
struct ASTTemplateArgumentListInfo {
- /// \brief The source location of the left angle bracket ('<');
+ /// \brief The source location of the left angle bracket ('<').
SourceLocation LAngleLoc;
- /// \brief The source location of the right angle bracket ('>');
+ /// \brief The source location of the right angle bracket ('>').
SourceLocation RAngleLoc;
- /// \brief The number of template arguments in TemplateArgs.
- /// The actual template arguments (if any) are stored after the
- /// ExplicitTemplateArgumentList structure.
- unsigned NumTemplateArgs;
-
+ union {
+ /// \brief The number of template arguments in TemplateArgs.
+ /// The actual template arguments (if any) are stored after the
+ /// ExplicitTemplateArgumentList structure.
+ unsigned NumTemplateArgs;
+
+ /// Force ASTTemplateArgumentListInfo to the right alignment
+ /// for the following array of TemplateArgumentLocs.
+ void *Aligner;
+ };
+
/// \brief Retrieve the template arguments
TemplateArgumentLoc *getTemplateArgs() {
return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 1d1c1d172573f..11a878d6b0f34 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -1061,7 +1061,6 @@ public:
struct FunctionLocInfo {
SourceLocation LocalRangeBegin;
SourceLocation LocalRangeEnd;
- bool TrailingReturn;
};
/// \brief Wrapper for source info for functions.
@@ -1084,13 +1083,6 @@ public:
getLocalData()->LocalRangeEnd = L;
}
- bool getTrailingReturn() const {
- return getLocalData()->TrailingReturn;
- }
- void setTrailingReturn(bool Trailing) {
- getLocalData()->TrailingReturn = Trailing;
- }
-
ArrayRef<ParmVarDecl *> getParams() const {
return ArrayRef<ParmVarDecl *>(getParmArray(), getNumArgs());
}
@@ -1119,7 +1111,6 @@ public:
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setLocalRangeBegin(Loc);
setLocalRangeEnd(Loc);
- setTrailingReturn(false);
for (unsigned i = 0, e = getNumArgs(); i != e; ++i)
setArg(i, NULL);
}
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 37e82e8318dde..33ef3dc8d6e0c 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -50,6 +50,7 @@
#include "clang/ASTMatchers/ASTMatchersMacros.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Regex.h"
+#include <iterator>
namespace clang {
namespace ast_matchers {
@@ -195,6 +196,75 @@ AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument,
return false;
}
+/// \brief Matches expressions that match InnerMatcher after any implicit casts
+/// are stripped off.
+///
+/// Parentheses and explicit casts are not discarded.
+/// Given
+/// int arr[5];
+/// int a = 0;
+/// char b = 0;
+/// const int c = a;
+/// int *d = arr;
+/// long e = (long) 0l;
+/// The matchers
+/// variable(hasInitializer(ignoringImpCasts(integerLiteral())))
+/// variable(hasInitializer(ignoringImpCasts(declarationReference())))
+/// would match the declarations for a, b, c, and d, but not e.
+/// while
+/// variable(hasInitializer(integerLiteral()))
+/// variable(hasInitializer(declarationReference()))
+/// only match the declarations for b, c, and d.
+AST_MATCHER_P(Expr, ignoringImpCasts,
+ internal::Matcher<Expr>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.IgnoreImpCasts(), Finder, Builder);
+}
+
+/// \brief Matches expressions that match InnerMatcher after parentheses and
+/// casts are stripped off.
+///
+/// Implicit and non-C Style casts are also discarded.
+/// Given
+/// int a = 0;
+/// char b = (0);
+/// void* c = reinterpret_cast<char*>(0);
+/// char d = char(0);
+/// The matcher
+/// variable(hasInitializer(ignoringParenCasts(integerLiteral())))
+/// would match the declarations for a, b, c, and d.
+/// while
+/// variable(hasInitializer(integerLiteral()))
+/// only match the declaration for a.
+AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher<Expr>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.IgnoreParenCasts(), Finder, Builder);
+}
+
+/// \brief Matches expressions that match InnerMatcher after implicit casts and
+/// parentheses are stripped off.
+///
+/// Explicit casts are not discarded.
+/// Given
+/// int arr[5];
+/// int a = 0;
+/// char b = (0);
+/// const int c = a;
+/// int *d = (arr);
+/// long e = ((long) 0l);
+/// The matchers
+/// variable(hasInitializer(ignoringParenImpCasts(
+/// integerLiteral())))
+/// variable(hasInitializer(ignoringParenImpCasts(
+/// declarationReference())))
+/// would match the declarations for a, b, c, and d, but not e.
+/// while
+/// variable(hasInitializer(integerLiteral()))
+/// variable(hasInitializer(declarationReference()))
+/// would only match the declaration for a.
+AST_MATCHER_P(Expr, ignoringParenImpCasts,
+ internal::Matcher<Expr>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.IgnoreParenImpCasts(), Finder, Builder);
+}
+
/// \brief Matches classTemplateSpecializations where the n'th TemplateArgument
/// matches the given Matcher.
///
@@ -691,6 +761,19 @@ const internal::VariadicDynCastAllOfMatcher<
Expr,
ImplicitCastExpr> implicitCast;
+/// \brief Matches any cast nodes of Clang's AST.
+///
+/// Example: castExpr() matches each of the following:
+/// (int) 3;
+/// const_cast<Expr *>(SubExpr);
+/// char c = 0;
+/// but does not match
+/// int i = (0);
+/// int k = 0;
+const internal::VariadicDynCastAllOfMatcher<
+ Expr,
+ CastExpr> castExpr;
+
/// \brief Matches functional cast expressions
///
/// Example: Matches Foo(bar);
@@ -1193,6 +1276,21 @@ AST_MATCHER_P(DeclRefExpr, throughUsingDecl,
return false;
}
+/// \brief Matches the Decl of a DeclStmt which has a single declaration.
+///
+/// Given
+/// int a, b;
+/// int c;
+/// declarationStatement(hasSingleDecl(anything()))
+/// matches 'int c;' but not 'int a, b;'.
+AST_MATCHER_P(DeclStmt, hasSingleDecl, internal::Matcher<Decl>, InnerMatcher) {
+ if (Node.isSingleDecl()) {
+ const Decl *FoundDecl = Node.getSingleDecl();
+ return InnerMatcher.matches(*FoundDecl, Finder, Builder);
+ }
+ return false;
+}
+
/// \brief Matches a variable declaration that has an initializer expression
/// that matches the given matcher.
///
@@ -1238,6 +1336,44 @@ AST_POLYMORPHIC_MATCHER_P2(
*Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
}
+/// \brief Matches declaration statements that contain a specific number of
+/// declarations.
+///
+/// Example: Given
+/// int a, b;
+/// int c;
+/// int d = 2, e;
+/// declCountIs(2)
+/// matches 'int a, b;' and 'int d = 2, e;', but not 'int c;'.
+AST_MATCHER_P(DeclStmt, declCountIs, unsigned, N) {
+ return std::distance(Node.decl_begin(), Node.decl_end()) == N;
+}
+
+/// \brief Matches the n'th declaration of a declaration statement.
+///
+/// Note that this does not work for global declarations because the AST
+/// breaks up multiple-declaration DeclStmt's into multiple single-declaration
+/// DeclStmt's.
+/// Example: Given non-global declarations
+/// int a, b = 0;
+/// int c;
+/// int d = 2, e;
+/// declarationStatement(containsDeclaration(
+/// 0, variable(hasInitializer(anything()))))
+/// matches only 'int d = 2, e;', and
+/// declarationStatement(containsDeclaration(1, variable()))
+/// matches 'int a, b = 0' as well as 'int d = 2, e;'
+/// but 'int c;' is not matched.
+AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N,
+ internal::Matcher<Decl>, InnerMatcher) {
+ const unsigned NumDecls = std::distance(Node.decl_begin(), Node.decl_end());
+ if (N >= NumDecls)
+ return false;
+ DeclStmt::const_decl_iterator Iterator = Node.decl_begin();
+ std::advance(Iterator, N);
+ return InnerMatcher.matches(**Iterator, Finder, Builder);
+}
+
/// \brief Matches a constructor initializer.
///
/// Given
@@ -1385,6 +1521,18 @@ AST_MATCHER_P(FunctionDecl, returns, internal::Matcher<QualType>, Matcher) {
return Matcher.matches(Node.getResultType(), Finder, Builder);
}
+/// \brief Matches extern "C" function declarations.
+///
+/// Given:
+/// extern "C" void f() {}
+/// extern "C" { void g() {} }
+/// void h() {}
+/// function(isExternC())
+/// matches the declaration of f and g, but not the declaration h
+AST_MATCHER(FunctionDecl, isExternC) {
+ return Node.isExternC();
+}
+
/// \brief Matches the condition expression of an if statement, for loop,
/// or conditional operator.
///
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 99180e450e65a..fade83ef9361c 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -826,6 +826,27 @@ def SharedLocksRequired : InheritableAttr {
let TemplateDependent = 1;
}
+// Type safety attributes for `void *' pointers and type tags.
+
+def ArgumentWithTypeTag : InheritableAttr {
+ let Spellings = [GNU<"argument_with_type_tag">,
+ GNU<"pointer_with_type_tag">];
+ let Args = [IdentifierArgument<"ArgumentKind">,
+ UnsignedArgument<"ArgumentIdx">,
+ UnsignedArgument<"TypeTagIdx">,
+ BoolArgument<"IsPointer">];
+ let Subjects = [Function];
+}
+
+def TypeTagForDatatype : InheritableAttr {
+ let Spellings = [GNU<"type_tag_for_datatype">];
+ let Args = [IdentifierArgument<"ArgumentKind">,
+ TypeArgument<"MatchingCType">,
+ BoolArgument<"LayoutCompatible">,
+ BoolArgument<"MustBeNull">];
+ let Subjects = [Var];
+}
+
// Microsoft-related attributes
def MsStruct : InheritableAttr {
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 1b060a509232c..84b28811728ef 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -376,9 +376,9 @@ BUILTIN(__builtin_ctz , "iUi" , "nc")
BUILTIN(__builtin_ctzl , "iULi" , "nc")
BUILTIN(__builtin_ctzll, "iULLi", "nc")
// TODO: int ctzimax(uintmax_t)
-BUILTIN(__builtin_ffs , "iUi" , "nc")
-BUILTIN(__builtin_ffsl , "iULi" , "nc")
-BUILTIN(__builtin_ffsll, "iULLi", "nc")
+BUILTIN(__builtin_ffs , "ii" , "nc")
+BUILTIN(__builtin_ffsl , "iLi" , "nc")
+BUILTIN(__builtin_ffsll, "iLLi", "nc")
BUILTIN(__builtin_parity , "iUi" , "nc")
BUILTIN(__builtin_parityl , "iULi" , "nc")
BUILTIN(__builtin_parityll, "iULLi", "nc")
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index b95a90bd21c3d..d8632dd8c39d6 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -155,6 +155,8 @@ def MethodAccess : DiagGroup<"objc-method-access">;
def ObjCReceiver : DiagGroup<"receiver-expr">;
def OverlengthStrings : DiagGroup<"overlength-strings">;
def OverloadedVirtual : DiagGroup<"overloaded-virtual">;
+def PrivateExtern : DiagGroup<"private-extern">;
+def SelTypeCast : DiagGroup<"cast-of-sel-type">;
def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">;
def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">;
def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">;
@@ -341,6 +343,8 @@ def FormatNonLiteral : DiagGroup<"format-nonliteral", [FormatSecurity]>;
def Format2 : DiagGroup<"format=2",
[FormatNonLiteral, FormatSecurity, FormatY2K]>;
+def TypeSafety : DiagGroup<"type-safety">;
+
def Extra : DiagGroup<"extra", [
MissingFieldInitializers,
IgnoredQualifiers,
@@ -371,7 +375,9 @@ def Most : DiagGroup<"most", [
Unused,
VolatileRegisterVar,
ObjCMissingSuperCalls,
- OverloadedVirtual
+ OverloadedVirtual,
+ PrivateExtern,
+ SelTypeCast
]>;
// Thread Safety warnings
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 8cb82fd4a9149..b1c16fa8529f1 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -677,6 +677,10 @@ def warn_availability_and_unavailable : Warning<
"'unavailable' availability overrides all other availability information">,
InGroup<Availability>;
+// Type safety attributes
+def err_type_safety_unknown_flag : Error<
+ "invalid comparison flag %0; use 'layout_compatible' or 'must_be_null'">;
+
// Language specific pragmas
// - Generic warnings
def warn_pragma_expected_lparen : Warning<
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 6d7b52e55f58f..2d63dc42fd94a 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -815,7 +815,7 @@ def err_friend_def_in_local_class : Error<
"friend function cannot be defined in a local class">;
def err_abstract_type_in_decl : Error<
- "%select{return|parameter|variable|field}0 type %1 is an abstract class">;
+ "%select{return|parameter|variable|field|ivar}0 type %1 is an abstract class">;
def err_allocation_of_abstract_type : Error<
"allocating an object of abstract class type %0">;
def err_throw_abstract_type : Error<
@@ -1489,6 +1489,11 @@ def note_non_literal_user_provided_dtor : Note<
"%0 is not literal because it has a user-provided destructor">;
def note_non_literal_nontrivial_dtor : Note<
"%0 is not literal because it has a non-trivial destructor">;
+def warn_private_extern : Warning<
+ "Use of __private_extern__ on tentative definition has unexpected"
+ " behaviour - use __attribute__((visibility(\"hidden\"))) on extern"
+ " declaration or definition instead">,
+ InGroup<PrivateExtern>, DefaultIgnore;
// C++11 char16_t/char32_t
def warn_cxx98_compat_unicode_type : Warning<
@@ -1542,6 +1547,8 @@ def err_attribute_argument_n_not_int : Error<
"'%0' attribute requires parameter %1 to be an integer constant">;
def err_attribute_argument_n_not_string : Error<
"'%0' attribute requires parameter %1 to be a string">;
+def err_attribute_argument_n_not_identifier : Error<
+ "'%0' attribute requires parameter %1 to be an identifier">;
def err_attribute_argument_out_of_bounds : Error<
"'%0' attribute parameter %1 is out of bounds">;
def err_attribute_requires_objc_interface : Error<
@@ -1550,6 +1557,8 @@ def err_attribute_uuid_malformed_guid : Error<
"uuid attribute contains a malformed GUID">;
def warn_nonnull_pointers_only : Warning<
"nonnull attribute only applies to pointer arguments">;
+def err_attribute_pointers_only : Error<
+ "'%0' attribute only applies to pointer arguments">;
def err_attribute_invalid_implicit_this_argument : Error<
"'%0' attribute is invalid for the implicit this argument">;
def err_ownership_type : Error<
@@ -1765,7 +1774,6 @@ def err_attribute_can_be_applied_only_to_value_decl : Error<
def warn_attribute_not_on_decl : Error<
"%0 attribute ignored when parsing type">;
-
// Availability attribute
def warn_availability_unknown_platform : Warning<
"unknown platform %0 in availability macro">, InGroup<Availability>;
@@ -3677,6 +3685,10 @@ def err_illegal_decl_array_of_references : Error<
"'%0' declared as array of references of type %1">;
def err_decl_negative_array_size : Error<
"'%0' declared as an array with a negative size">;
+def err_array_static_outside_prototype : Error<
+ "%0 used in array declarator outside of function prototype">;
+def err_array_static_not_outermost : Error<
+ "%0 used in non-outermost array type derivation">;
def err_array_star_outside_prototype : Error<
"star modifier used outside of function prototype">;
def err_illegal_decl_pointer_to_reference : Error<
@@ -4953,6 +4965,9 @@ def err_typecheck_cast_to_union_no_type : Error<
"cast to union type from type %0 not present in union">;
def err_cast_pointer_from_non_pointer_int : Error<
"operand of type %0 cannot be cast to a pointer type">;
+def warn_cast_pointer_from_sel : Warning<
+ "cast of type %0 to %1 is deprecated; use sel_getName instead">,
+ InGroup<SelTypeCast>;
def err_cast_pointer_to_non_pointer_int : Error<
"pointer cannot be cast to type %0">;
def err_typecheck_expect_scalar_operand : Error<
@@ -5467,6 +5482,23 @@ def warn_identity_field_assign : Warning<
"assigning %select{field|instance variable}0 to itself">,
InGroup<SelfAssignmentField>;
+// Type safety attributes
+def err_type_tag_for_datatype_not_ice : Error<
+ "'type_tag_for_datatype' attribute requires the initializer to be "
+ "an %select{integer|integral}0 constant expression">;
+def err_type_tag_for_datatype_too_large : Error<
+ "'type_tag_for_datatype' attribute requires the initializer to be "
+ "an %select{integer|integral}0 constant expression "
+ "that can be represented by a 64 bit integer">;
+def warn_type_tag_for_datatype_wrong_kind : Warning<
+ "this type tag was not designed to be used with this function">,
+ InGroup<TypeSafety>;
+def warn_type_safety_type_mismatch : Warning<
+ "argument type %0 doesn't match specified '%1' type tag "
+ "%select{that requires %3|}2">, InGroup<TypeSafety>;
+def warn_type_safety_null_pointer_required : Warning<
+ "specified %0 type tag requires a null pointer">, InGroup<TypeSafety>;
+
// Generic selections.
def err_assoc_type_incomplete : Error<
"type %0 in generic association incomplete">;
diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h
index 25a49038a863d..44f9ab39f3216 100644
--- a/include/clang/Lex/PTHManager.h
+++ b/include/clang/Lex/PTHManager.h
@@ -101,7 +101,7 @@ class PTHManager : public IdentifierInfoLookup {
public:
// The current PTH version.
- enum { Version = 9 };
+ enum { Version = 10 };
~PTHManager();
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 353b59e0ae324..4ef92f7dbc69f 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1834,6 +1834,10 @@ private:
ParsedAttributes &Attrs,
SourceLocation *EndLoc);
+ void ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs,
+ SourceLocation *EndLoc);
void ParseTypeofSpecifier(DeclSpec &DS);
SourceLocation ParseDecltypeSpecifier(DeclSpec &DS);
diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h
index 5239044e67080..bf358862b09eb 100644
--- a/include/clang/Sema/AttributeList.h
+++ b/include/clang/Sema/AttributeList.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/SmallVector.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/VersionTuple.h"
+#include "clang/Sema/Ownership.h"
#include <cassert>
namespace clang {
@@ -87,6 +88,10 @@ private:
/// availability attribute.
unsigned IsAvailability : 1;
+ /// True if this has extra information associated with a
+ /// type_tag_for_datatype attribute.
+ unsigned IsTypeTagForDatatype : 1;
+
unsigned AttrKind : 8;
/// \brief The location of the 'unavailable' keyword in an
@@ -119,6 +124,22 @@ private:
return reinterpret_cast<const AvailabilityChange*>(this+1)[index];
}
+public:
+ struct TypeTagForDatatypeData {
+ ParsedType *MatchingCType;
+ unsigned LayoutCompatible : 1;
+ unsigned MustBeNull : 1;
+ };
+
+private:
+ TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
+ return *reinterpret_cast<TypeTagForDatatypeData *>(this + 1);
+ }
+
+ const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
+ return *reinterpret_cast<const TypeTagForDatatypeData *>(this + 1);
+ }
+
AttributeList(const AttributeList &); // DO NOT IMPLEMENT
void operator=(const AttributeList &); // DO NOT IMPLEMENT
void operator delete(void *); // DO NOT IMPLEMENT
@@ -126,6 +147,7 @@ private:
size_t allocated_size() const;
+ /// Constructor for attributes with expression arguments.
AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
IdentifierInfo *parmName, SourceLocation parmLoc,
@@ -134,12 +156,13 @@ private:
: AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
NumArgs(numArgs), SyntaxUsed(syntaxUsed), Invalid(false),
- UsedAsTypeAttr(false), IsAvailability(false),
- NextInPosition(0), NextInPool(0) {
+ UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) {
if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*));
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
+ /// Constructor for availability attributes.
AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
IdentifierInfo *parmName, SourceLocation parmLoc,
@@ -153,6 +176,7 @@ private:
AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
NumArgs(0), SyntaxUsed(syntaxUsed),
Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
+ IsTypeTagForDatatype(false),
UnavailableLoc(unavailable), MessageExpr(messageExpr),
NextInPosition(0), NextInPool(0) {
new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
@@ -161,6 +185,25 @@ private:
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
+ /// Constructor for type_tag_for_datatype attribute.
+ AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *argumentKindName,
+ SourceLocation argumentKindLoc,
+ ParsedType matchingCType, bool layoutCompatible,
+ bool mustBeNull, Syntax syntaxUsed)
+ : AttrName(attrName), ScopeName(scopeName), ParmName(argumentKindName),
+ AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(argumentKindLoc),
+ NumArgs(0), SyntaxUsed(syntaxUsed),
+ Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(true), NextInPosition(NULL), NextInPool(NULL) {
+ TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
+ new (&ExtraData.MatchingCType) ParsedType(matchingCType);
+ ExtraData.LayoutCompatible = layoutCompatible;
+ ExtraData.MustBeNull = mustBeNull;
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ }
+
friend class AttributePool;
friend class AttributeFactory;
@@ -279,6 +322,24 @@ public:
assert(getKind() == AT_Availability && "Not an availability attribute");
return MessageExpr;
}
+
+ const ParsedType &getMatchingCType() const {
+ assert(getKind() == AT_TypeTagForDatatype &&
+ "Not a type_tag_for_datatype attribute");
+ return *getTypeTagForDatatypeDataSlot().MatchingCType;
+ }
+
+ bool getLayoutCompatible() const {
+ assert(getKind() == AT_TypeTagForDatatype &&
+ "Not a type_tag_for_datatype attribute");
+ return getTypeTagForDatatypeDataSlot().LayoutCompatible;
+ }
+
+ bool getMustBeNull() const {
+ assert(getKind() == AT_TypeTagForDatatype &&
+ "Not a type_tag_for_datatype attribute");
+ return getTypeTagForDatatypeDataSlot().MustBeNull;
+ }
};
/// A factory, from which one makes pools, from which one creates
@@ -294,7 +355,11 @@ public:
AvailabilityAllocSize =
sizeof(AttributeList)
+ ((3 * sizeof(AvailabilityChange) + sizeof(void*) - 1)
- / sizeof(void*) * sizeof(void*))
+ / sizeof(void*) * sizeof(void*)),
+ TypeTagForDatatypeAllocSize =
+ sizeof(AttributeList)
+ + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) - 1)
+ / sizeof(void*) * sizeof(void*)
};
private:
@@ -411,6 +476,21 @@ public:
AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
SourceLocation TokLoc, int Arg);
+
+ AttributeList *createTypeTagForDatatype(
+ IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *argumentKindName,
+ SourceLocation argumentKindLoc,
+ ParsedType matchingCType, bool layoutCompatible,
+ bool mustBeNull, AttributeList::Syntax syntax) {
+ void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
+ return add(new (memory) AttributeList(attrName, attrRange,
+ scopeName, scopeLoc,
+ argumentKindName, argumentKindLoc,
+ matchingCType, layoutCompatible,
+ mustBeNull, syntax));
+ }
};
/// addAttributeLists - Add two AttributeLists together
@@ -503,7 +583,7 @@ public:
/// dependencies on this method, it may not be long-lived.
AttributeList *&getListRef() { return list; }
-
+ /// Add attribute with expression arguments.
AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
IdentifierInfo *parmName, SourceLocation parmLoc,
@@ -516,6 +596,7 @@ public:
return attr;
}
+ /// Add availability attribute.
AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
IdentifierInfo *parmName, SourceLocation parmLoc,
@@ -533,6 +614,24 @@ public:
return attr;
}
+ /// Add type_tag_for_datatype attribute.
+ AttributeList *addNewTypeTagForDatatype(
+ IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *argumentKindName,
+ SourceLocation argumentKindLoc,
+ ParsedType matchingCType, bool layoutCompatible,
+ bool mustBeNull, AttributeList::Syntax syntax) {
+ AttributeList *attr =
+ pool.createTypeTagForDatatype(attrName, attrRange,
+ scopeName, scopeLoc,
+ argumentKindName, argumentKindLoc,
+ matchingCType, layoutCompatible,
+ mustBeNull, syntax);
+ add(attr);
+ return attr;
+ }
+
AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name,
SourceLocation loc, int arg) {
AttributeList *attr =
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 058e0d9d39206..acc88c0578ed7 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2498,13 +2498,11 @@ public:
ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc,
Expr *collection);
StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
- SourceLocation LParenLoc,
Stmt *First, Expr *collection,
SourceLocation RParenLoc);
StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body);
- StmtResult ActOnCXXForRangeStmt(SourceLocation ForLoc,
- SourceLocation LParenLoc, Stmt *LoopVar,
+ StmtResult ActOnCXXForRangeStmt(SourceLocation ForLoc, Stmt *LoopVar,
SourceLocation ColonLoc, Expr *Collection,
SourceLocation RParenLoc);
StmtResult BuildCXXForRangeStmt(SourceLocation ForLoc,
@@ -2542,8 +2540,8 @@ public:
bool MSAsm = false);
StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc,
+ SourceLocation LBraceLoc,
ArrayRef<Token> AsmToks,
- ArrayRef<unsigned> LineEnds,
SourceLocation EndLoc);
VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
@@ -4463,6 +4461,7 @@ public:
AbstractParamType,
AbstractVariableType,
AbstractFieldType,
+ AbstractIvarType,
AbstractArrayType
};
@@ -7146,6 +7145,42 @@ private:
void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field,
Expr *Init);
+public:
+ /// \brief Register a magic integral constant to be used as a type tag.
+ void RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind,
+ uint64_t MagicValue, QualType Type,
+ bool LayoutCompatible, bool MustBeNull);
+
+ struct TypeTagData {
+ TypeTagData() {}
+
+ TypeTagData(QualType Type, bool LayoutCompatible, bool MustBeNull) :
+ Type(Type), LayoutCompatible(LayoutCompatible),
+ MustBeNull(MustBeNull)
+ {}
+
+ QualType Type;
+
+ /// If true, \c Type should be compared with other expression's types for
+ /// layout-compatibility.
+ unsigned LayoutCompatible : 1;
+ unsigned MustBeNull : 1;
+ };
+
+ /// A pair of ArgumentKind identifier and magic value. This uniquely
+ /// identifies the magic value.
+ typedef std::pair<const IdentifierInfo *, uint64_t> TypeTagMagicValue;
+
+private:
+ /// \brief A map from magic value to type information.
+ OwningPtr<llvm::DenseMap<TypeTagMagicValue, TypeTagData> >
+ TypeTagForDatatypeMagicValues;
+
+ /// \brief Peform checks on a call of a function with argument_with_type_tag
+ /// or pointer_with_type_tag attributes.
+ void CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
+ const Expr * const *ExprArgs);
+
/// \brief The parser's current scope.
///
/// The parser maintains this state here.
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 5ee52cc615890..48393a379b39e 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -81,15 +81,19 @@ protected:
typedef llvm::DenseSet<SymbolRef> Symbols;
typedef llvm::DenseSet<const MemRegion *> Regions;
- /// A set of symbols that are registered with this report as being
+ /// A (stack of) a set of symbols that are registered with this
+ /// report as being "interesting", and thus used to help decide which
+ /// diagnostics to include when constructing the final path diagnostic.
+ /// The stack is largely used by BugReporter when generating PathDiagnostics
+ /// for multiple PathDiagnosticConsumers.
+ llvm::SmallVector<Symbols *, 2> interestingSymbols;
+
+ /// A (stack of) set of regions that are registered with this report as being
/// "interesting", and thus used to help decide which diagnostics
/// to include when constructing the final path diagnostic.
- Symbols interestingSymbols;
-
- /// A set of regions that are registered with this report as being
- /// "interesting", and thus used to help decide which diagnostics
- /// to include when constructing the final path diagnostic.
- Regions interestingRegions;
+ /// The stack is largely used by BugReporter when generating PathDiagnostics
+ /// for multiple PathDiagnosticConsumers.
+ llvm::SmallVector<Regions *, 2> interestingRegions;
/// A set of custom visitors which generate "event" diagnostics at
/// interesting points in the path.
@@ -107,6 +111,15 @@ protected:
/// when reporting an issue.
bool DoNotPrunePath;
+private:
+ // Used internally by BugReporter.
+ Symbols &getInterestingSymbols();
+ Regions &getInterestingRegions();
+
+ void lazyInitializeInterestingSets();
+ void pushInterestingSymbolsAndRegions();
+ void popInterestingSymbolsAndRegions();
+
public:
BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode)
: BT(bt), DeclWithIssue(0), Description(desc), ErrorNode(errornode),
@@ -160,9 +173,9 @@ public:
void markInteresting(const MemRegion *R);
void markInteresting(SVal V);
- bool isInteresting(SymbolRef sym) const;
- bool isInteresting(const MemRegion *R) const;
- bool isInteresting(SVal V) const;
+ bool isInteresting(SymbolRef sym);
+ bool isInteresting(const MemRegion *R);
+ bool isInteresting(SVal V);
unsigned getConfigurationChangeToken() const {
return ConfigurationChangeToken;
@@ -295,7 +308,7 @@ class BugReporterData {
public:
virtual ~BugReporterData();
virtual DiagnosticsEngine& getDiagnostic() = 0;
- virtual PathDiagnosticConsumer* getPathDiagnosticConsumer() = 0;
+ virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
virtual ASTContext &getASTContext() = 0;
virtual SourceManager& getSourceManager() = 0;
};
@@ -318,6 +331,12 @@ private:
/// Generate and flush the diagnostics for the given bug report.
void FlushReport(BugReportEquivClass& EQ);
+ /// Generate and flush the diagnostics for the given bug report
+ /// and PathDiagnosticConsumer.
+ void FlushReport(BugReport *exampleReport,
+ PathDiagnosticConsumer &PD,
+ ArrayRef<BugReport*> BugReports);
+
/// The set of bug reports tracked by the BugReporter.
llvm::FoldingSet<BugReportEquivClass> EQClasses;
/// A vector of BugReports for tracking the allocated pointers and cleanup.
@@ -341,8 +360,8 @@ public:
return D.getDiagnostic();
}
- PathDiagnosticConsumer* getPathDiagnosticConsumer() {
- return D.getPathDiagnosticConsumer();
+ ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() {
+ return D.getPathDiagnosticConsumers();
}
/// \brief Iterator over the set of BugTypes tracked by the BugReporter.
@@ -360,7 +379,8 @@ public:
SourceManager& getSourceManager() { return D.getSourceManager(); }
virtual void GeneratePathDiagnostic(PathDiagnostic& pathDiagnostic,
- SmallVectorImpl<BugReport *> &bugReports) {}
+ PathDiagnosticConsumer &PC,
+ ArrayRef<BugReport *> &bugReports) {}
void Register(BugType *BT);
@@ -421,7 +441,8 @@ public:
ProgramStateManager &getStateManager();
virtual void GeneratePathDiagnostic(PathDiagnostic &pathDiagnostic,
- SmallVectorImpl<BugReport*> &bugReports);
+ PathDiagnosticConsumer &PC,
+ ArrayRef<BugReport*> &bugReports);
/// classof - Used by isa<>, cast<>, and dyn_cast<>.
static bool classof(const BugReporter* R) {
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index 2e7abfa5cc3bb..973cfb109c050 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -51,22 +51,25 @@ typedef const SymExpr* SymbolRef;
class PathDiagnostic;
class PathDiagnosticConsumer {
+public:
+ typedef std::vector<std::pair<StringRef, std::string> > FilesMade;
+
+private:
virtual void anchor();
public:
PathDiagnosticConsumer() : flushed(false) {}
virtual ~PathDiagnosticConsumer();
- void FlushDiagnostics(SmallVectorImpl<std::string> *FilesMade);
+ void FlushDiagnostics(FilesMade *FilesMade);
virtual void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
- SmallVectorImpl<std::string> *FilesMade)
- = 0;
+ FilesMade *filesMade) = 0;
virtual StringRef getName() const = 0;
void HandlePathDiagnostic(PathDiagnostic *D);
- enum PathGenerationScheme { Minimal, Extensive };
+ enum PathGenerationScheme { None, Minimal, Extensive };
virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
virtual bool supportsLogicalOpControlFlow() const { return false; }
virtual bool supportsAllBlockEdges() const { return false; }
@@ -332,15 +335,8 @@ public:
ranges.push_back(SourceRange(B,E));
}
- typedef const SourceRange* range_iterator;
-
- range_iterator ranges_begin() const {
- return ranges.empty() ? NULL : &ranges[0];
- }
-
- range_iterator ranges_end() const {
- return ranges_begin() + ranges.size();
- }
+ /// Return the SourceRanges associated with this PathDiagnosticPiece.
+ ArrayRef<SourceRange> getRanges() const { return ranges; }
static inline bool classof(const PathDiagnosticPiece *P) {
return true;
diff --git a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
index 65be3a406b433..3aab648dc5741 100644
--- a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
+++ b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_GR_PATH_DIAGNOSTIC_CLIENTS_H
#include <string>
+#include <vector>
namespace clang {
@@ -23,24 +24,25 @@ class Preprocessor;
namespace ento {
class PathDiagnosticConsumer;
+typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers;
-PathDiagnosticConsumer*
-createHTMLDiagnosticConsumer(const std::string& prefix, const Preprocessor &PP);
+void createHTMLDiagnosticConsumer(PathDiagnosticConsumers &C,
+ const std::string& prefix,
+ const Preprocessor &PP);
-PathDiagnosticConsumer*
-createPlistDiagnosticConsumer(const std::string& prefix, const Preprocessor &PP,
- PathDiagnosticConsumer *SubPD = 0);
+void createPlistDiagnosticConsumer(PathDiagnosticConsumers &C,
+ const std::string& prefix,
+ const Preprocessor &PP);
-PathDiagnosticConsumer*
-createPlistMultiFileDiagnosticConsumer(const std::string& prefix,
- const Preprocessor &PP);
+void createPlistMultiFileDiagnosticConsumer(PathDiagnosticConsumers &C,
+ const std::string& prefix,
+ const Preprocessor &PP);
-PathDiagnosticConsumer*
-createTextPathDiagnosticConsumer(const std::string& prefix,
- const Preprocessor &PP);
+void createTextPathDiagnosticConsumer(PathDiagnosticConsumers &C,
+ const std::string& prefix,
+ const Preprocessor &PP);
-} // end GR namespace
-
-} // end clang namespace
+} // end 'ento' namespace
+} // end 'clang' namespace
#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index 1cc53d4423dac..876196ba4f7fd 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -19,6 +19,7 @@
#include "clang/Frontend/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
namespace clang {
@@ -32,8 +33,7 @@ class AnalysisManager : public BugReporterData {
ASTContext &Ctx;
DiagnosticsEngine &Diags;
const LangOptions &LangOpts;
-
- OwningPtr<PathDiagnosticConsumer> PD;
+ PathDiagnosticConsumers PathConsumers;
// Configurable components creators.
StoreManagerCreator CreateStoreMgr;
@@ -82,8 +82,9 @@ public:
bool NoRetryExhausted;
public:
- AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
- const LangOptions &lang, PathDiagnosticConsumer *pd,
+ AnalysisManager(ASTContext &ctx,DiagnosticsEngine &diags,
+ const LangOptions &lang,
+ const PathDiagnosticConsumers &Consumers,
StoreManagerCreator storemgr,
ConstraintManagerCreator constraintmgr,
CheckerManager *checkerMgr,
@@ -99,12 +100,7 @@ public:
AnalysisInliningMode inliningMode,
bool NoRetry);
- /// Construct a clone of the given AnalysisManager with the given ASTContext
- /// and DiagnosticsEngine.
- AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
- AnalysisManager &ParentAM);
-
- ~AnalysisManager() { FlushDiagnostics(); }
+ ~AnalysisManager();
void ClearContexts() {
AnaCtxMgr.clear();
@@ -140,15 +136,12 @@ public:
return LangOpts;
}
- virtual PathDiagnosticConsumer *getPathDiagnosticConsumer() {
- return PD.get();
- }
-
- void FlushDiagnostics() {
- if (PD.get())
- PD->FlushDiagnostics(0);
+ ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() {
+ return PathConsumers;
}
+ void FlushDiagnostics();
+
unsigned getMaxNodes() const { return MaxNodes; }
unsigned getMaxVisit() const { return MaxVisit; }
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index 47edfe9fca91e..f6c5830c2955f 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -328,7 +328,7 @@ public:
// For debugging purposes only
void dump(raw_ostream &Out) const;
- LLVM_ATTRIBUTE_USED void dump() const { dump(llvm::errs()); }
+ LLVM_ATTRIBUTE_USED void dump() const;
static bool classof(const CallEvent *) { return true; }
};
@@ -804,8 +804,12 @@ public:
return getOriginExpr()->getReceiverInterface();
}
+ /// Returns how the message was written in the source (property access,
+ /// subscript, or explicit message send).
ObjCMessageKind getMessageKind() const;
+ /// Returns true if this property access or subscript is a setter (has the
+ /// form of an assignment).
bool isSetter() const {
switch (getMessageKind()) {
case OCM_Message:
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 01218effff90d..8044ed839a75e 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -52,7 +52,9 @@ class RegionOffset {
int64_t Offset;
public:
- enum { Symbolic = INT64_MAX };
+ // We're using a const instead of an enumeration due to the size required;
+ // Visual Studio will only create enumerations of size int, not long long.
+ static const int64_t Symbolic = INT64_MAX;
RegionOffset() : R(0) {}
RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index d36aa1bd1bcbe..b0c51dd5b9285 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -65,10 +65,14 @@ class DynamicTypeInfo {
public:
DynamicTypeInfo() : T(QualType()) {}
- DynamicTypeInfo(QualType WithType, bool CanBeSub = true):
- T(WithType), CanBeASubClass(CanBeSub) {}
- QualType getType() { return T; }
- bool canBeASubClass() { return CanBeASubClass; }
+ DynamicTypeInfo(QualType WithType, bool CanBeSub = true)
+ : T(WithType), CanBeASubClass(CanBeSub) {}
+
+ bool isValid() const { return !T.isNull(); }
+
+ QualType getType() const { return T; }
+ bool canBeASubClass() const { return CanBeASubClass; }
+
void Profile(llvm::FoldingSetNodeID &ID) const {
T.Profile(ID);
ID.AddInteger((unsigned)CanBeASubClass);