summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbdoulaye Walsimou Gaye <awg@embtoolkit.org>2013-05-15 21:40:27 +0200
committerAbdoulaye Walsimou Gaye <awg@embtoolkit.org>2013-05-15 21:40:27 +0200
commitb0274c7c30af17c0255846bcd53cac4f7d76ddea (patch)
tree4243e33459039a96c26557de48f989e85c925a4c
parent38f7a3147aad1e25d0738356519cf9235f5c80b7 (diff)
parentcce70c7c5f0f4c1a41658fbed845f8b3a565c99c (diff)
downloadclang-embtk-support-master.tar.gz
clang-embtk-support-master.tar.bz2
clang-embtk-support-master.tar.xz
Merge branch 'master' into embtk-support-masterembtk-support-master
Signed-off-by: Abdoulaye Walsimou Gaye <awg@embtoolkit.org>
-rw-r--r--docs/LeakSanitizer.rst28
-rw-r--r--include/clang/AST/Attr.h2
-rw-r--r--include/clang/AST/CanonicalType.h2
-rw-r--r--include/clang/AST/CharUnits.h21
-rw-r--r--include/clang/AST/Decl.h24
-rw-r--r--include/clang/AST/DeclFriend.h2
-rw-r--r--include/clang/AST/DeclObjC.h4
-rw-r--r--include/clang/AST/DeclOpenMP.h26
-rw-r--r--include/clang/AST/DeclarationName.h12
-rw-r--r--include/clang/AST/ExprCXX.h2
-rw-r--r--include/clang/AST/ExternalASTSource.h7
-rw-r--r--include/clang/AST/NestedNameSpecifier.h6
-rw-r--r--include/clang/AST/Stmt.h3
-rw-r--r--include/clang/AST/StmtIterator.h5
-rw-r--r--include/clang/AST/Type.h2
-rw-r--r--include/clang/AST/TypeLoc.h2
-rw-r--r--include/clang/ASTMatchers/ASTMatchFinder.h11
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h6
-rw-r--r--include/clang/ASTMatchers/Dynamic/Diagnostics.h109
-rw-r--r--include/clang/ASTMatchers/Dynamic/Parser.h143
-rw-r--r--include/clang/ASTMatchers/Dynamic/Registry.h63
-rw-r--r--include/clang/ASTMatchers/Dynamic/VariantValue.h125
-rw-r--r--include/clang/Analysis/Analyses/FormatString.h2
-rw-r--r--include/clang/Analysis/CFG.h2
-rw-r--r--include/clang/Basic/AttrKinds.h2
-rw-r--r--include/clang/Basic/BuiltinsARM.def2
-rw-r--r--include/clang/Basic/Diagnostic.h2
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td5
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td28
-rw-r--r--include/clang/Basic/Linkage.h5
-rw-r--r--include/clang/Format/Format.h32
-rw-r--r--include/clang/Frontend/ASTUnit.h2
-rw-r--r--include/clang/Frontend/CompilerInstance.h10
-rw-r--r--include/clang/Frontend/FrontendAction.h2
-rw-r--r--include/clang/Lex/HeaderSearch.h2
-rw-r--r--include/clang/Lex/MacroInfo.h2
-rw-r--r--include/clang/Lex/ModuleMap.h2
-rw-r--r--include/clang/Lex/Preprocessor.h2
-rw-r--r--include/clang/Parse/Parser.h11
-rw-r--r--include/clang/Sema/Initialization.h12
-rw-r--r--include/clang/Sema/Ownership.h2
-rw-r--r--include/clang/Sema/Sema.h21
-rw-r--r--include/clang/Sema/TypoCorrection.h2
-rw-r--r--include/clang/Serialization/ASTReader.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/Checker.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h2
-rw-r--r--lib/ARCMigrate/TransUnbridgedCasts.cpp4
-rw-r--r--lib/ARCMigrate/Transforms.cpp4
-rw-r--r--lib/AST/ASTContext.cpp99
-rw-r--r--lib/AST/ASTDiagnostic.cpp3
-rw-r--r--lib/AST/ASTDumper.cpp6
-rw-r--r--lib/AST/ASTImporter.cpp10
-rw-r--r--lib/AST/Decl.cpp31
-rw-r--r--lib/AST/DeclOpenMP.cpp10
-rw-r--r--lib/AST/DeclPrinter.cpp4
-rw-r--r--lib/AST/DeclarationName.cpp142
-rw-r--r--lib/AST/Expr.cpp2
-rw-r--r--lib/AST/ExprConstant.cpp157
-rw-r--r--lib/AST/ItaniumMangle.cpp4
-rw-r--r--lib/AST/MicrosoftMangle.cpp96
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp4
-rw-r--r--lib/AST/Type.cpp4
-rw-r--r--lib/ASTMatchers/ASTMatchFinder.cpp8
-rw-r--r--lib/ASTMatchers/CMakeLists.txt2
-rw-r--r--lib/ASTMatchers/Dynamic/CMakeLists.txt16
-rw-r--r--lib/ASTMatchers/Dynamic/Diagnostics.cpp113
-rw-r--r--lib/ASTMatchers/Dynamic/Makefile13
-rw-r--r--lib/ASTMatchers/Dynamic/Marshallers.h223
-rw-r--r--lib/ASTMatchers/Dynamic/Parser.cpp332
-rw-r--r--lib/ASTMatchers/Dynamic/Registry.cpp153
-rw-r--r--lib/ASTMatchers/Dynamic/VariantValue.cpp105
-rw-r--r--lib/ASTMatchers/Makefile2
-rw-r--r--lib/Analysis/CFG.cpp2
-rw-r--r--lib/Basic/OpenMPKinds.cpp3
-rw-r--r--lib/Basic/Targets.cpp38
-rw-r--r--lib/CodeGen/CGBuiltin.cpp5
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp21
-rw-r--r--lib/CodeGen/CGDebugInfo.h2
-rw-r--r--lib/CodeGen/CGVTables.cpp2
-rw-r--r--lib/CodeGen/CodeGenFunction.h2
-rw-r--r--lib/CodeGen/CodeGenModule.cpp2
-rw-r--r--lib/CodeGen/CodeGenTBAA.cpp3
-rw-r--r--lib/Format/Format.cpp191
-rw-r--r--lib/Format/TokenAnnotator.cpp12
-rw-r--r--lib/Format/TokenAnnotator.h9
-rw-r--r--lib/Format/UnwrappedLineParser.cpp25
-rw-r--r--lib/Format/UnwrappedLineParser.h7
-rw-r--r--lib/Format/WhitespaceManager.cpp12
-rw-r--r--lib/Format/WhitespaceManager.h2
-rw-r--r--lib/Lex/HeaderMap.cpp2
-rw-r--r--lib/Lex/PPDirectives.cpp2
-rw-r--r--lib/Lex/PPLexerChange.cpp2
-rw-r--r--lib/Parse/ParseDecl.cpp2
-rw-r--r--lib/Parse/ParseOpenMP.cpp93
-rw-r--r--lib/Parse/ParseStmt.cpp2
-rw-r--r--lib/Parse/Parser.cpp5
-rw-r--r--lib/Parse/RAIIObjectsForParser.h7
-rw-r--r--lib/Rewrite/Core/Rewriter.cpp2
-rw-r--r--lib/Sema/DeclSpec.cpp2
-rw-r--r--lib/Sema/Sema.cpp8
-rw-r--r--lib/Sema/SemaDecl.cpp22
-rw-r--r--lib/Sema/SemaDeclCXX.cpp4
-rw-r--r--lib/Sema/SemaDeclObjC.cpp4
-rw-r--r--lib/Sema/SemaExpr.cpp10
-rw-r--r--lib/Sema/SemaExprObjC.cpp9
-rw-r--r--lib/Sema/SemaInit.cpp167
-rw-r--r--lib/Sema/SemaLookup.cpp2
-rw-r--r--lib/Sema/SemaOpenMP.cpp230
-rw-r--r--lib/Sema/SemaTemplate.cpp4
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp8
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp8
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp93
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp4
-rw-r--r--lib/StaticAnalyzer/Core/CheckerContext.cpp2
-rw-r--r--test/Analysis/NSContainers.m33
-rw-r--r--test/Analysis/inlining/DynDispatchBifurcate.m4
-rw-r--r--test/Analysis/inlining/path-notes.m492
-rw-r--r--test/Analysis/rdar-6540084.m4
-rw-r--r--test/CodeGen/arm-clear.c17
-rw-r--r--test/CodeGen/arm-neon-vget.c124
-rw-r--r--test/CodeGen/linux-arm-atomic.c11
-rw-r--r--test/CodeGenCXX/captured-statements.cpp11
-rw-r--r--test/CodeGenCXX/cxx1y-deduced-return-type.cpp32
-rw-r--r--test/CodeGenCXX/debug-info-namespace.cpp27
-rw-r--r--test/CodeGenCXX/debug-info-template.cpp23
-rw-r--r--test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp41
-rw-r--r--test/CodeGenCXX/mangle-ms-templates.cpp26
-rw-r--r--test/CodeGenCXX/mangle-ms.cpp20
-rw-r--r--test/Format/diagnostic.cpp4
-rw-r--r--test/Index/comment-to-html-xml-conversion.cpp4
-rw-r--r--test/Lexer/char-literal.cpp4
-rw-r--r--test/Misc/ast-dump-templates.cpp12
-rw-r--r--test/Modules/objc-categories.m1
-rw-r--r--test/OpenMP/predefined_macro.c1
-rw-r--r--test/OpenMP/threadprivate_messages.cpp52
-rw-r--r--test/PCH/chain-categories2.m1
-rw-r--r--test/Preprocessor/init.c8
-rw-r--r--test/Sema/builtins-aarch64.c5
-rw-r--r--test/Sema/builtins-arm.c16
-rw-r--r--test/Sema/ms-wchar.c5
-rw-r--r--test/Sema/offsetof-64.c15
-rw-r--r--test/Sema/offsetof.c1
-rw-r--r--test/Sema/string-init.c51
-rw-r--r--test/Sema/warn-documentation.m21
-rw-r--r--test/Sema/wchar.c4
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp8
-rw-r--r--test/SemaCXX/constant-expression-cxx1y.cpp119
-rw-r--r--test/SemaCXX/enum-unscoped-nonexistent.cpp4
-rw-r--r--test/SemaCXX/ms-wchar.cpp3
-rw-r--r--test/SemaCXX/nested-name-spec.cpp10
-rw-r--r--test/SemaCXX/string-init.cpp40
-rw-r--r--test/SemaObjC/call-super-2.m2
-rw-r--r--test/SemaObjC/compare-qualified-id.m2
-rw-r--r--test/SemaObjC/conditional-expr.m3
-rw-r--r--test/SemaObjC/error-outof-scope-property-use.m2
-rw-r--r--test/SemaObjC/instancetype.m2
-rw-r--r--test/SemaObjC/message.m2
-rw-r--r--test/SemaObjC/method-not-defined.m2
-rw-r--r--test/SemaObjC/missing-atend-metadata.m2
-rw-r--r--test/SemaObjC/property-5.m2
-rw-r--r--test/SemaObjC/protocol-id-test-1.m2
-rw-r--r--test/SemaObjCXX/instancetype.mm2
-rw-r--r--test/Tooling/auto-detect-from-source-parent-of-cwd.cpp2
-rw-r--r--test/Tooling/clang-check-pwd.cpp2
-rw-r--r--tools/clang-format/clang-format.el44
-rw-r--r--tools/driver/cc1as_main.cpp6
-rw-r--r--tools/libclang/CIndex.cpp2
-rw-r--r--tools/libclang/CIndexUSRs.cpp7
-rw-r--r--tools/libclang/IndexingContext.cpp3
-rw-r--r--unittests/ASTMatchers/ASTMatchersTest.h35
-rw-r--r--unittests/ASTMatchers/CMakeLists.txt2
-rw-r--r--unittests/ASTMatchers/Dynamic/CMakeLists.txt7
-rw-r--r--unittests/ASTMatchers/Dynamic/Makefile20
-rw-r--r--unittests/ASTMatchers/Dynamic/ParserTest.cpp194
-rw-r--r--unittests/ASTMatchers/Dynamic/RegistryTest.cpp112
-rw-r--r--unittests/ASTMatchers/Dynamic/VariantValueTest.cpp97
-rw-r--r--unittests/ASTMatchers/Makefile2
-rw-r--r--unittests/Format/FormatTest.cpp248
-rw-r--r--unittests/Tooling/CompilationDatabaseTest.cpp4
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp16
-rw-r--r--utils/TableGen/NeonEmitter.cpp13
-rw-r--r--www/cxx_status.html2
184 files changed, 4480 insertions, 965 deletions
diff --git a/docs/LeakSanitizer.rst b/docs/LeakSanitizer.rst
new file mode 100644
index 0000000000..09d02cfcd5
--- /dev/null
+++ b/docs/LeakSanitizer.rst
@@ -0,0 +1,28 @@
+================
+LeakSanitizer
+================
+
+.. contents::
+ :local:
+
+Introduction
+============
+
+LeakSanitizer is a heap leak detector which is designed to be used on top of
+:doc:`AddressSanitizer` / :doc:`MemorySanitizer`, or as a standalone library.
+LeakSanitizer is a run-time tool which doesn't require compiler
+instrumentation.
+
+Current status
+==============
+
+LeakSanitizer is a work in progress, currently under development for
+x86\_64 Linux.
+
+More Information
+================
+
+Design wiki:
+`https://code.google.com/p/address-sanitizer/wiki/LeakSanitizerDesignDocument
+<https://code.google.com/p/address-sanitizer/wiki/LeakSanitizerDesignDocument>`_
+
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 27dcef2a1e..e07e84a783 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -145,7 +145,7 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
// Relies on relative order of enum emission with respect to param attrs.
- return (A->getKind() <= attr::LAST_MS_INHERITABLE &&
+ return (A->getKind() <= attr::LAST_MS_INHERITANCE &&
A->getKind() > attr::LAST_INHERITABLE_PARAM);
}
};
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 946075739d..9c699b7e0a 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -81,7 +81,7 @@ public:
operator QualType() const { return Stored; }
/// \brief Implicit conversion to bool.
- operator bool() const { return !isNull(); }
+ LLVM_EXPLICIT operator bool() const { return !isNull(); }
bool isNull() const {
return Stored.isNull();
diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h
index 082c672c21..09ff6828ef 100644
--- a/include/clang/AST/CharUnits.h
+++ b/include/clang/AST/CharUnits.h
@@ -19,21 +19,20 @@
#include "llvm/Support/MathExtras.h"
namespace clang {
-
+
/// CharUnits - This is an opaque type for sizes expressed in character units.
- /// Instances of this type represent a quantity as a multiple of the size
+ /// Instances of this type represent a quantity as a multiple of the size
/// of the standard C type, char, on the target architecture. As an opaque
/// type, CharUnits protects you from accidentally combining operations on
- /// quantities in bit units and character units.
+ /// quantities in bit units and character units.
+ ///
+ /// In both C and C++, an object of type 'char', 'signed char', or 'unsigned
+ /// char' occupies exactly one byte, so 'character unit' and 'byte' refer to
+ /// the same quantity of storage. However, we use the term 'character unit'
+ /// rather than 'byte' to avoid an implication that a character unit is
+ /// exactly 8 bits.
///
- /// It should be noted that characters and bytes are distinct concepts. Bytes
- /// refer to addressable units of data storage on the target machine, and
- /// characters are members of a set of elements used for the organization,
- /// control, or representation of data. According to C99, bytes are allowed
- /// to exceed characters in size, although currently, clang only supports
- /// architectures where the two are the same size.
- ///
- /// For portability, never assume that a target character is 8 bits wide. Use
+ /// For portability, never assume that a target character is 8 bits wide. Use
/// CharUnit values wherever you calculate sizes, offsets, or alignments
/// in character units.
class CharUnits {
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index d5e6ebee4a..aafd0bc530 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -24,6 +24,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/raw_ostream.h"
namespace clang {
struct ASTTemplateArgumentListInfo;
@@ -142,7 +143,7 @@ public:
// FIXME: Deprecated, move clients to getName().
std::string getNameAsString() const { return Name.getAsString(); }
- void printName(raw_ostream &os) const { return Name.printName(os); }
+ void printName(raw_ostream &os) const { os << Name; }
/// getDeclName - Get the actual, stored name of the declaration,
/// which may be a special name.
@@ -212,11 +213,26 @@ public:
bool isCXXInstanceMember() const;
/// \brief Determine what kind of linkage this entity has.
- Linkage getLinkage() const;
+ /// This is not the linkage as defined by the standard or the codegen notion
+ /// of linkage. It is just an implementation detail that is used to compute
+ /// those.
+ Linkage getLinkageInternal() const;
+
+ /// \brief Get the linkage from a semantic point of view. Entities in
+ /// anonymous namespaces are external (in c++98).
+ Linkage getFormalLinkage() const {
+ Linkage L = getLinkageInternal();
+ if (L == UniqueExternalLinkage)
+ return ExternalLinkage;
+ return L;
+ }
/// \brief True if this decl has external linkage.
- bool hasExternalLinkage() const {
- return getLinkage() == ExternalLinkage;
+ bool hasExternalFormalLinkage() const {
+ return getFormalLinkage() == ExternalLinkage;
+ }
+ bool isExternallyVisible() const {
+ return getLinkageInternal() == ExternalLinkage;
}
/// \brief Determines the visibility of this entity.
diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index 3a12878e74..589178ec6e 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/include/clang/AST/DeclFriend.h
@@ -228,7 +228,7 @@ inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
}
inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
- assert(FD->NextFriend == 0 && "friend already has next friend?");
+ assert(!FD->NextFriend && "friend already has next friend?");
FD->NextFriend = data().FirstFriend;
data().FirstFriend = FD;
}
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 40de0135a7..0028240349 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -452,7 +452,7 @@ public:
}
/// \brief Determine whether this method has a body.
- virtual bool hasBody() const { return Body; }
+ virtual bool hasBody() const { return Body.isValid(); }
/// \brief Retrieve the body of this method, if it has one.
virtual Stmt *getBody() const;
@@ -463,7 +463,7 @@ public:
void setBody(Stmt *B) { Body = B; }
/// \brief Returns whether this specific method is a definition.
- bool isThisDeclarationADefinition() const { return Body; }
+ bool isThisDeclarationADefinition() const { return hasBody(); }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h
index ca92040c32..42fe907aa1 100644
--- a/include/clang/AST/DeclOpenMP.h
+++ b/include/clang/AST/DeclOpenMP.h
@@ -1,4 +1,4 @@
-//===--- OpenMP.h - Classes for representing OpenMP directives ---*- C++ -*-===//
+//===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file defines OpenMP nodes.
+/// \brief This file defines OpenMP nodes for declarative directives.
///
//===----------------------------------------------------------------------===//
@@ -20,8 +20,6 @@
namespace clang {
-class DeclRefExpr;
-
/// \brief This represents '#pragma omp threadprivate ...' directive.
/// For example, in the following, both 'a' and 'A::b' are threadprivate:
///
@@ -43,29 +41,29 @@ class OMPThreadPrivateDecl : public Decl {
OMPThreadPrivateDecl(Kind DK, DeclContext *DC, SourceLocation L) :
Decl(DK, DC, L), NumVars(0) { }
- ArrayRef<const DeclRefExpr *> getVars() const {
- return ArrayRef<const DeclRefExpr *>(
- reinterpret_cast<const DeclRefExpr * const *>(this + 1),
+ ArrayRef<const Expr *> getVars() const {
+ return ArrayRef<const Expr *>(
+ reinterpret_cast<const Expr * const *>(this + 1),
NumVars);
}
- llvm::MutableArrayRef<DeclRefExpr *> getVars() {
- return llvm::MutableArrayRef<DeclRefExpr *>(
- reinterpret_cast<DeclRefExpr **>(this + 1),
+ llvm::MutableArrayRef<Expr *> getVars() {
+ return llvm::MutableArrayRef<Expr *>(
+ reinterpret_cast<Expr **>(this + 1),
NumVars);
}
- void setVars(ArrayRef<DeclRefExpr *> VL);
+ void setVars(ArrayRef<Expr *> VL);
public:
static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
- ArrayRef<DeclRefExpr *> VL);
+ ArrayRef<Expr *> VL);
static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C,
unsigned ID, unsigned N);
- typedef llvm::MutableArrayRef<DeclRefExpr *>::iterator varlist_iterator;
- typedef ArrayRef<const DeclRefExpr *>::iterator varlist_const_iterator;
+ typedef llvm::MutableArrayRef<Expr *>::iterator varlist_iterator;
+ typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
unsigned varlist_size() const { return NumVars; }
bool varlist_empty() const { return NumVars == 0; }
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index f28882b3bf..00766c27c1 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -182,11 +182,16 @@ public:
// operator bool() - Evaluates true when this declaration name is
// non-empty.
- operator bool() const {
+ LLVM_EXPLICIT operator bool() const {
return ((Ptr & PtrMask) != 0) ||
(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask));
}
+ /// \brief Evaluates true when this declaration name is empty.
+ bool isEmpty() const {
+ return !*this;
+ }
+
/// Predicate functions for querying what type of name this is.
bool isIdentifier() const { return getStoredNameKind() == StoredIdentifier; }
bool isObjCZeroArgSelector() const {
@@ -210,9 +215,6 @@ public:
/// getNameAsString - Retrieve the human-readable string for this name.
std::string getAsString() const;
- /// printName - Print the human-readable name to a stream.
- void printName(raw_ostream &OS) const;
-
/// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in
/// this declaration name, or NULL if this declaration name isn't a
/// simple identifier.
@@ -302,6 +304,8 @@ public:
void dump() const;
};
+raw_ostream &operator<<(raw_ostream &OS, DeclarationName N);
+
/// Ordering on two declaration names. If both names are identifiers,
/// this provides a lexicographical ordering.
inline bool operator<(DeclarationName LHS, DeclarationName RHS) {
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 91e5b21eac..a4f296c988 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -1935,7 +1935,7 @@ public:
/// \brief Determines whether this member expression actually had
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
/// x->Base::foo.
- bool hasQualifier() const { return QualifierLoc; }
+ bool hasQualifier() const { return QualifierLoc.hasQualifier(); }
/// \brief Retrieves the nested-name-specifier that qualifies the type name,
/// with source-location information.
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index 81fcf242b6..b077426e6a 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/include/clang/AST/ExternalASTSource.h
@@ -329,7 +329,12 @@ public:
/// \brief Whether this pointer is non-NULL.
///
/// This operation does not require the AST node to be deserialized.
- operator bool() const { return Ptr != 0; }
+ LLVM_EXPLICIT operator bool() const { return Ptr != 0; }
+
+ /// \brief Whether this pointer is non-NULL.
+ ///
+ /// This operation does not require the AST node to be deserialized.
+ bool isValid() const { return Ptr != 0; }
/// \brief Whether this pointer is currently stored as an offset.
bool isOffset() const { return Ptr & 0x01; }
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index 58f39862b1..b332b153fe 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -231,7 +231,11 @@ public:
/// \brief Evalutes true when this nested-name-specifier location is
/// non-empty.
- operator bool() const { return Qualifier; }
+ LLVM_EXPLICIT operator bool() const { return Qualifier; }
+
+ /// \brief Evalutes true when this nested-name-specifier location is
+ /// empty.
+ bool hasQualifier() const { return Qualifier; }
/// \brief Retrieve the nested-name-specifier to which this instance
/// refers.
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 74c9ec2053..b2ab672627 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -967,9 +967,6 @@ public:
SwitchCase *getSwitchCaseList() { return FirstCase; }
/// \brief Set the case list for this switch statement.
- ///
- /// The caller is responsible for incrementing the retain counts on
- /// all of the SwitchCase statements in this list.
void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; }
SourceLocation getSwitchLoc() const { return SwitchLoc; }
diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h
index b933ed0762..fc25fa9a6e 100644
--- a/include/clang/AST/StmtIterator.h
+++ b/include/clang/AST/StmtIterator.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_STMT_ITR_H
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Compiler.h"
#include <cassert>
#include <cstddef>
#include <iterator>
@@ -156,7 +157,7 @@ struct StmtRange : std::pair<StmtIterator,StmtIterator> {
: std::pair<StmtIterator,StmtIterator>(begin, end) {}
bool empty() const { return first == second; }
- operator bool() const { return !empty(); }
+ LLVM_EXPLICIT operator bool() const { return !empty(); }
Stmt *operator->() const { return first.operator->(); }
Stmt *&operator*() const { return first.operator*(); }
@@ -199,7 +200,7 @@ struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> {
: std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
bool empty() const { return first == second; }
- operator bool() const { return !empty(); }
+ LLVM_EXPLICIT operator bool() const { return !empty(); }
const Stmt *operator->() const { return first.operator->(); }
const Stmt *operator*() const { return first.operator*(); }
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 39f10d3393..93c287fd18 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -441,7 +441,7 @@ public:
bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; }
- operator bool() const { return hasQualifiers(); }
+ LLVM_EXPLICIT operator bool() const { return hasQualifiers(); }
Qualifiers &operator+=(Qualifiers R) {
addQualifiers(R);
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 11cad9bb9d..9e2d3bffb9 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -90,7 +90,7 @@ public:
}
bool isNull() const { return !Ty; }
- operator bool() const { return Ty; }
+ LLVM_EXPLICIT operator bool() const { return Ty; }
/// \brief Returns the size of type source info data block for the given type.
static unsigned getFullDataSizeForType(QualType Ty);
diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h
index 870a39b391..be58afffd1 100644
--- a/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -131,6 +131,17 @@ public:
MatchCallback *Action);
/// @}
+ /// \brief Adds a matcher to execute when running over the AST.
+ ///
+ /// This is similar to \c addMatcher(), but it uses the dynamic interface. It
+ /// is more flexible, but the lost type information enables a caller to pass
+ /// a matcher that cannot match anything.
+ ///
+ /// \returns \c true if the matcher is a valid top-level matcher, \c false
+ /// otherwise.
+ bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
+ MatchCallback *Action);
+
/// \brief Creates a clang ASTConsumer that finds all matches.
clang::ASTConsumer *newASTConsumer();
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index 30691ad8f9..bc4ddce36f 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -239,6 +239,9 @@ public:
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const = 0;
+ /// \brief Makes a copy of this matcher object.
+ virtual DynTypedMatcher *clone() const = 0;
+
/// \brief Returns a unique ID for the matcher.
virtual uint64_t getID() const = 0;
};
@@ -301,6 +304,9 @@ public:
return matches(*Node, Finder, Builder);
}
+ /// \brief Makes a copy of this matcher object.
+ virtual Matcher<T> *clone() const { return new Matcher<T>(*this); }
+
/// \brief Allows the conversion of a \c Matcher<Type> to a \c
/// Matcher<QualType>.
///
diff --git a/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
new file mode 100644
index 0000000000..417bc67967
--- /dev/null
+++ b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
@@ -0,0 +1,109 @@
+//===--- Diagnostics.h - Helper class for error diagnostics -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Diagnostics class to manage error messages.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
+
+#include <string>
+#include <vector>
+
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+struct SourceLocation {
+ SourceLocation() : Line(), Column() {}
+ unsigned Line;
+ unsigned Column;
+};
+
+struct SourceRange {
+ SourceLocation Start;
+ SourceLocation End;
+};
+
+/// \brief A VariantValue instance annotated with its parser context.
+struct ParserValue {
+ ParserValue() : Text(), Range(), Value() {}
+ StringRef Text;
+ SourceRange Range;
+ VariantValue Value;
+};
+
+/// \brief Helper class to manage error messages.
+class Diagnostics {
+ public:
+ /// \brief All errors from the system.
+ enum ErrorType {
+ ET_None = 0,
+
+ ET_RegistryNotFound = 1,
+ ET_RegistryWrongArgCount = 2,
+ ET_RegistryWrongArgType = 3,
+
+ ET_ParserStringError = 100,
+ ET_ParserMatcherArgFailure = 101,
+ ET_ParserMatcherFailure = 102,
+ ET_ParserNoOpenParen = 103,
+ ET_ParserNoCloseParen = 104,
+ ET_ParserNoComma = 105,
+ ET_ParserNoCode = 106,
+ ET_ParserNotAMatcher = 107,
+ ET_ParserInvalidToken = 108
+ };
+
+ /// \brief Helper stream class.
+ struct ArgStream {
+ template <class T> ArgStream &operator<<(const T &Arg) {
+ return operator<<(Twine(Arg));
+ }
+ ArgStream &operator<<(const Twine &Arg);
+ std::vector<std::string> *Out;
+ };
+
+ /// \brief Push a frame to the beginning of the list
+ ///
+ /// Returns a helper class to allow the caller to pass the arguments for the
+ /// error message, using the << operator.
+ ArgStream pushErrorFrame(const SourceRange &Range, ErrorType Error);
+
+ struct ErrorFrame {
+ SourceRange Range;
+ ErrorType Type;
+ std::vector<std::string> Args;
+
+ std::string ToString() const;
+ };
+ ArrayRef<ErrorFrame> frames() const { return Frames; }
+
+ /// \brief Returns a string representation of the last frame.
+ std::string ToString() const;
+ /// \brief Returns a string representation of the whole frame stack.
+ std::string ToStringFull() const;
+
+ private:
+ std::vector<ErrorFrame> Frames;
+};
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h
new file mode 100644
index 0000000000..f981c6055e
--- /dev/null
+++ b/include/clang/ASTMatchers/Dynamic/Parser.h
@@ -0,0 +1,143 @@
+//===--- Parser.h - Matcher expression parser -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Simple matcher expression parser.
+///
+/// The parser understands matcher expressions of the form:
+/// MatcherName(Arg0, Arg1, ..., ArgN)
+/// as well as simple types like strings.
+/// The parser does not know how to process the matchers. It delegates this task
+/// to a Sema object received as an argument.
+///
+/// \code
+/// Grammar for the expressions supported:
+/// <Expression> := <StringLiteral> | <MatcherExpression>
+/// <StringLiteral> := "quoted string"
+/// <MatcherExpression> := <MatcherName>(<ArgumentList>)
+/// <MatcherName> := [a-zA-Z]+
+/// <ArgumentList> := <Expression> | <Expression>,<ArgumentList>
+/// \endcode
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
+
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+/// \brief Matcher expression parser.
+class Parser {
+public:
+ /// \brief Interface to connect the parser with the registry and more.
+ ///
+ /// The parser uses the Sema instance passed into
+ /// parseMatcherExpression() to handle all matcher tokens. The simplest
+ /// processor implementation would simply call into the registry to create
+ /// the matchers.
+ /// However, a more complex processor might decide to intercept the matcher
+ /// creation and do some extra work. For example, it could apply some
+ /// transformation to the matcher by adding some id() nodes, or could detect
+ /// specific matcher nodes for more efficient lookup.
+ class Sema {
+ public:
+ virtual ~Sema();
+
+ /// \brief Process a matcher expression.
+ ///
+ /// All the arguments passed here have already been processed.
+ ///
+ /// \param MatcherName The matcher name found by the parser.
+ ///
+ /// \param NameRange The location of the name in the matcher source.
+ /// Useful for error reporting.
+ ///
+ /// \param Args The argument list for the matcher.
+ ///
+ /// \return The matcher object constructed by the processor, or NULL
+ /// if an error occurred. In that case, \c Error will contain a
+ /// description of the error.
+ /// The caller takes ownership of the DynTypedMatcher object returned.
+ virtual DynTypedMatcher *
+ actOnMatcherExpression(StringRef MatcherName, const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args, Diagnostics *Error) = 0;
+ };
+
+ /// \brief Parse a matcher expression, creating matchers from the registry.
+ ///
+ /// This overload creates matchers calling directly into the registry. If the
+ /// caller needs more control over how the matchers are created, then it can
+ /// use the overload below that takes a Sema.
+ ///
+ /// \param MatcherCode The matcher expression to parse.
+ ///
+ /// \return The matcher object constructed, or NULL if an error occurred.
+ // In that case, \c Error will contain a description of the error.
+ /// The caller takes ownership of the DynTypedMatcher object returned.
+ static DynTypedMatcher *parseMatcherExpression(StringRef MatcherCode,
+ Diagnostics *Error);
+
+ /// \brief Parse a matcher expression.
+ ///
+ /// \param MatcherCode The matcher expression to parse.
+ ///
+ /// \param S The Sema instance that will help the parser
+ /// construct the matchers.
+ /// \return The matcher object constructed by the processor, or NULL
+ /// if an error occurred. In that case, \c Error will contain a
+ /// description of the error.
+ /// The caller takes ownership of the DynTypedMatcher object returned.
+ static DynTypedMatcher *parseMatcherExpression(StringRef MatcherCode,
+ Sema *S,
+ Diagnostics *Error);
+
+ /// \brief Parse an expression, creating matchers from the registry.
+ ///
+ /// Parses any expression supported by this parser. In general, the
+ /// \c parseMatcherExpression function is a better approach to get a matcher
+ /// object.
+ static bool parseExpression(StringRef Code, VariantValue *Value,
+ Diagnostics *Error);
+
+ /// \brief Parse an expression.
+ ///
+ /// Parses any expression supported by this parser. In general, the
+ /// \c parseMatcherExpression function is a better approach to get a matcher
+ /// object.
+ static bool parseExpression(StringRef Code, Sema *S,
+ VariantValue *Value, Diagnostics *Error);
+
+private:
+ class CodeTokenizer;
+ struct TokenInfo;
+
+ Parser(CodeTokenizer *Tokenizer, Sema *S,
+ Diagnostics *Error);
+
+ bool parseExpressionImpl(VariantValue *Value);
+ bool parseMatcherExpressionImpl(VariantValue *Value);
+
+ CodeTokenizer *const Tokenizer;
+ Sema *const S;
+ Diagnostics *const Error;
+};
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
diff --git a/include/clang/ASTMatchers/Dynamic/Registry.h b/include/clang/ASTMatchers/Dynamic/Registry.h
new file mode 100644
index 0000000000..b092ed8fe1
--- /dev/null
+++ b/include/clang/ASTMatchers/Dynamic/Registry.h
@@ -0,0 +1,63 @@
+//===--- Registry.h - Matcher registry -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Registry of all known matchers.
+///
+/// The registry provides a generic interface to construct any matcher by name.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
+
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+class Registry {
+public:
+ /// \brief Construct a matcher from the registry by name.
+ ///
+ /// Consult the registry of known matchers and construct the appropriate
+ /// matcher by name.
+ ///
+ /// \param MatcherName The name of the matcher to instantiate.
+ ///
+ /// \param NameRange The location of the name in the matcher source.
+ /// Useful for error reporting.
+ ///
+ /// \param Args The argument list for the matcher. The number and types of the
+ /// values must be valid for the matcher requested. Otherwise, the function
+ /// will return an error.
+ ///
+ /// \return The matcher if no error was found. NULL if the matcher is not
+ // found, or if the number of arguments or argument types do not
+ /// match the signature. In that case \c Error will contain the description
+ /// of the error.
+ static DynTypedMatcher *constructMatcher(StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error);
+
+private:
+ Registry() LLVM_DELETED_FUNCTION;
+};
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h
new file mode 100644
index 0000000000..9a41b448cf
--- /dev/null
+++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h
@@ -0,0 +1,125 @@
+//===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Polymorphic value type.
+///
+/// Supports all the types required for dynamic Matcher construction.
+/// Used by the registry to construct matchers in a generic way.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchersInternal.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/type_traits.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+using ast_matchers::internal::DynTypedMatcher;
+
+/// \brief Variant value class.
+///
+/// Basically, a tagged union with value type semantics.
+/// It is used by the registry as the return value and argument type for the
+/// matcher factory methods.
+/// It can be constructed from any of the supported types. It supports
+/// copy/assignment.
+///
+/// Supported types:
+/// - \c std::string
+/// - \c DynTypedMatcher, and any \c Matcher<T>
+class VariantValue {
+public:
+ VariantValue() : Type(VT_Nothing) {}
+
+ VariantValue(const VariantValue &Other);
+ ~VariantValue();
+ VariantValue &operator=(const VariantValue &Other);
+
+ /// \brief Specific constructors for each supported type.
+ VariantValue(const std::string &String);
+ VariantValue(const DynTypedMatcher &Matcher);
+
+ /// \brief String value functions.
+ bool isString() const;
+ const std::string &getString() const;
+ void setString(const std::string &String);
+
+ /// \brief Matcher value functions.
+ bool isMatcher() const;
+ const DynTypedMatcher &getMatcher() const;
+ void setMatcher(const DynTypedMatcher &Matcher);
+ /// \brief Set the value to be \c Matcher by taking ownership of the object.
+ void takeMatcher(DynTypedMatcher *Matcher);
+
+ /// \brief Specialized Matcher<T> is/get functions.
+ template <class T>
+ bool isTypedMatcher() const {
+ // TODO: Add some logic to test if T is actually valid for the underlying
+ // type of the matcher.
+ return isMatcher();
+ }
+
+ template <class T>
+ ast_matchers::internal::Matcher<T> getTypedMatcher() const {
+ return ast_matchers::internal::makeMatcher(
+ new DerivedTypeMatcher<T>(getMatcher()));
+ }
+
+private:
+ void reset();
+
+ /// \brief Matcher bridge between a Matcher<T> and a generic DynTypedMatcher.
+ template <class T>
+ class DerivedTypeMatcher :
+ public ast_matchers::internal::MatcherInterface<T> {
+ public:
+ explicit DerivedTypeMatcher(const DynTypedMatcher &DynMatcher)
+ : DynMatcher(DynMatcher.clone()) {}
+ virtual ~DerivedTypeMatcher() {}
+
+ typedef ast_matchers::internal::ASTMatchFinder ASTMatchFinder;
+ typedef ast_matchers::internal::BoundNodesTreeBuilder BoundNodesTreeBuilder;
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return DynMatcher->matches(ast_type_traits::DynTypedNode::create(Node),
+ Finder, Builder);
+ }
+
+ private:
+ const OwningPtr<DynTypedMatcher> DynMatcher;
+ };
+
+ /// \brief All supported value types.
+ enum ValueType {
+ VT_Nothing,
+ VT_String,
+ VT_Matcher
+ };
+
+ /// \brief All supported value types.
+ union AllValues {
+ std::string *String;
+ DynTypedMatcher *Matcher;
+ };
+
+ ValueType Type;
+ AllValues Value;
+};
+
+} // end namespace dynamic
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h
index 4bd989cf4e..6ad89aec0a 100644
--- a/include/clang/Analysis/Analyses/FormatString.h
+++ b/include/clang/Analysis/Analyses/FormatString.h
@@ -49,7 +49,7 @@ public:
const char *toString() const { return representation; }
// Overloaded operators for bool like qualities
- operator bool() const { return flag; }
+ LLVM_EXPLICIT operator bool() const { return flag; }
OptionalFlag& operator=(const bool &rhs) {
flag = rhs;
return *this; // Return a reference to myself.
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index ee0be736dd..01480ed3b4 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -269,7 +269,7 @@ public:
Stmt &operator*() { return *getStmt(); }
const Stmt &operator*() const { return *getStmt(); }
- operator bool() const { return getStmt(); }
+ LLVM_EXPLICIT operator bool() const { return getStmt(); }
};
/// CFGBlock - Represents a single basic block in a source-level CFG.
diff --git a/include/clang/Basic/AttrKinds.h b/include/clang/Basic/AttrKinds.h
index bd090ecc0d..7c4e2c75f0 100644
--- a/include/clang/Basic/AttrKinds.h
+++ b/include/clang/Basic/AttrKinds.h
@@ -24,7 +24,7 @@ enum Kind {
#define ATTR(X) X,
#define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = X,
#define LAST_INHERITABLE_PARAM_ATTR(X) X, LAST_INHERITABLE_PARAM = X,
-#define LAST_MS_INHERITABLE_ATTR(X) X, LAST_MS_INHERITABLE = X,
+#define LAST_MS_INHERITANCE_ATTR(X) X, LAST_MS_INHERITANCE = X,
#include "clang/Basic/AttrList.inc"
NUM_ATTRS
};
diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def
index 888e529111..fad9007e04 100644
--- a/include/clang/Basic/BuiltinsARM.def
+++ b/include/clang/Basic/BuiltinsARM.def
@@ -15,7 +15,7 @@
// The format of this database matches clang/Basic/Builtins.def.
// In libgcc
-BUILTIN(__clear_cache, "v.", "")
+BUILTIN(__clear_cache, "vv*v*", "")
BUILTIN(__builtin_thread_pointer, "v*", "")
// Saturating arithmetic
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index 3e125944a3..1354120ea5 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -1212,7 +1212,7 @@ public:
~StoredDiagnostic();
/// \brief Evaluates true when this object stores a diagnostic.
- operator bool() const { return Message.size() > 0; }
+ LLVM_EXPLICIT operator bool() const { return Message.size() > 0; }
unsigned getID() const { return ID; }
DiagnosticsEngine::Level getLevel() const { return Level; }
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index e001bd46a2..a4b8d1810c 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -819,13 +819,14 @@ def err_seh___finally_block : Error<
def warn_pragma_omp_ignored : Warning <
"unexpected '#pragma omp ...' in program">, InGroup<SourceUsesOpenMP>, DefaultIgnore;
def warn_omp_extra_tokens_at_eol : Warning <
- "extra tokens at end of '#pragma omp %0' are ignored">,
+ "extra tokens at the end of '#pragma omp %0' are ignored">,
InGroup<ExtraTokens>;
def err_omp_unknown_directive : Error <
"expected an OpenMP directive">;
def err_omp_unexpected_directive : Error <
"unexpected OpenMP directive '#pragma omp %0'">;
-
+def err_omp_expected_var : Error <
+ "expected '#pragma omp %0' argument to be a variable name">;
} // end of Parse Issue category.
let CategoryName = "Modules Issue" in {
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 18d5796ea1..55f237736c 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -499,6 +499,8 @@ def note_while_in_implementation : Note<
"detected while default synthesizing properties in class implementation">;
def note_class_declared : Note<
"class is declared here">;
+def note_receiver_class_declared : Note<
+ "receiver is instance of class declared here">;
def note_receiver_is_id : Note<
"receiver is treated with 'id' type for purpose of method lookup">;
def note_suppressed_class_declare : Note<
@@ -4280,7 +4282,13 @@ def err_typecheck_incomplete_array_needs_initializer : Error<
"or an initializer">;
def err_array_init_not_init_list : Error<
"array initializer must be an initializer "
- "list%select{| or string literal}0">;
+ "list%select{| or string literal| or wide string literal}0">;
+def err_array_init_narrow_string_into_wchar : Error<
+ "initializing wide char array with non-wide string literal">;
+def err_array_init_wide_string_into_char : Error<
+ "initializing char array with wide string literal">;
+def err_array_init_incompat_wide_string_into_wchar : Error<
+ "initializing wide char array with incompatible wide string literal">;
def err_array_init_different_type : Error<
"cannot initialize array %diff{of type $ with array of type $|"
"with different type of array}0,1">;
@@ -6336,24 +6344,26 @@ def err_wrong_sampler_addressspace: Error<
"sampler type cannot be used with the __local and __global address space qualifiers">;
def err_opencl_global_invalid_addr_space : Error<
"global variables must have a constant address space qualifier">;
-
+
+} // end of sema category
+
+let CategoryName = "OpenMP Issue" in {
// OpenMP support.
def err_omp_expected_var_arg_suggest : Error<
"%0 is not a global variable, static local variable or static data member%select{|; did you mean %2?}1">;
def err_omp_global_var_arg : Error<
"arguments of '#pragma omp %0' must have %select{global storage|static storage duration}1">;
def err_omp_ref_type_arg : Error<
- "arguments of '#pragma omp %0' cannot be of reference type %1">;
+ "arguments of '#pragma omp %0' cannot be of reference type">;
def err_omp_var_scope : Error<
- "'#pragma omp %0' must appear in the scope of the %1 variable declaration">;
+ "'#pragma omp %0' must appear in the scope of the %q1 variable declaration">;
def err_omp_var_used : Error<
- "'#pragma omp %0' must precede all references to variable %1">;
+ "'#pragma omp %0' must precede all references to variable %q1">;
def err_omp_var_thread_local : Error<
"variable %0 cannot be threadprivate because it is thread-local">;
-def err_omp_incomplete_type : Error<
- "a threadprivate variable must not have incomplete type %0">;
-
-} // end of sema category
+def err_omp_threadprivate_incomplete_type : Error<
+ "threadprivate variable with incomplete type %0">;
+} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
// Objective-C related result type compatibility
diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
index 01b8db15f5..13d2d24d8e 100644
--- a/include/clang/Basic/Linkage.h
+++ b/include/clang/Basic/Linkage.h
@@ -62,11 +62,6 @@ enum GVALinkage {
GVA_ExplicitTemplateInstantiation
};
-/// \brief Determine whether the given linkage is semantically external.
-inline bool isExternalLinkage(Linkage L) {
- return L == UniqueExternalLinkage || L == ExternalLinkage;
-}
-
/// \brief Compute the minimum linkage given two linages.
inline Linkage minLinkage(Linkage L1, Linkage L2) {
return L1 < L2? L1 : L2;
diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
index 9d17c77db7..ba44c04024 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -94,6 +94,27 @@ struct FormatStyle {
/// Otherwise puts them into the right-most column.
bool AlignEscapedNewlinesLeft;
+ /// \brief The number of characters to use for indentation.
+ unsigned IndentWidth;
+
+ /// \brief If true, \c IndentWidth consecutive spaces will be replaced with
+ /// tab characters.
+ bool UseTab;
+
+ /// \brief Different ways to attach braces to their surrounding context.
+ enum BraceBreakingStyle {
+ /// Always attach braces to surrounding context.
+ BS_Attach,
+ /// Like \c Attach, but break before braces on function, namespace and
+ /// class definitions.
+ BS_Linux,
+ /// Like \c Attach, but break before function definitions.
+ BS_Stroustrup
+ };
+
+ /// \brief The brace breaking style to use.
+ BraceBreakingStyle BreakBeforeBraces;
+
bool operator==(const FormatStyle &R) const {
return AccessModifierOffset == R.AccessModifierOffset &&
AlignEscapedNewlinesLeft == R.AlignEscapedNewlinesLeft &&
@@ -113,7 +134,10 @@ struct FormatStyle {
PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine &&
PointerBindsToType == R.PointerBindsToType &&
SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
- Standard == R.Standard;
+ Standard == R.Standard &&
+ IndentWidth == R.IndentWidth &&
+ UseTab == R.UseTab &&
+ BreakBeforeBraces == R.BreakBeforeBraces;
}
};
@@ -153,15 +177,11 @@ std::string configurationAsText(const FormatStyle &Style);
/// everything that might influence its formatting or might be influenced by its
/// formatting.
///
-/// \param DiagClient A custom DiagnosticConsumer. Can be 0, in this case
-/// diagnostic is output to llvm::errs().
-///
/// Returns the \c Replacements necessary to make all \p Ranges comply with
/// \p Style.
tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
SourceManager &SourceMgr,
- std::vector<CharSourceRange> Ranges,
- DiagnosticConsumer *DiagClient = 0);
+ std::vector<CharSourceRange> Ranges);
/// \brief Returns the \c LangOpts that the formatter expects you to set.
LangOptions getFormattingLangOpts();
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 9bd0ef31e0..1fc56ce5f3 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -456,7 +456,7 @@ public:
void setASTContext(ASTContext *ctx) { Ctx = ctx; }
void setPreprocessor(Preprocessor *pp);
- bool hasSema() const { return TheSema; }
+ bool hasSema() const { return TheSema.isValid(); }
Sema &getSema() const {
assert(TheSema && "ASTUnit does not have a Sema object!");
return *TheSema;
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index dbd76066b9..ee4850580d 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -395,7 +395,7 @@ public:
/// @name ASTConsumer
/// {
- bool hasASTConsumer() const { return Consumer != 0; }
+ bool hasASTConsumer() const { return Consumer.isValid(); }
ASTConsumer &getASTConsumer() const {
assert(Consumer && "Compiler instance has no AST consumer!");
@@ -413,7 +413,7 @@ public:
/// }
/// @name Semantic analysis
/// {
- bool hasSema() const { return TheSema != 0; }
+ bool hasSema() const { return TheSema.isValid(); }
Sema &getSema() const {
assert(TheSema && "Compiler instance has no Sema object!");
@@ -433,7 +433,9 @@ public:
/// @name Code Completion
/// {
- bool hasCodeCompletionConsumer() const { return CompletionConsumer != 0; }
+ bool hasCodeCompletionConsumer() const {
+ return CompletionConsumer.isValid();
+ }
CodeCompleteConsumer &getCodeCompletionConsumer() const {
assert(CompletionConsumer &&
@@ -455,7 +457,7 @@ public:
/// @name Frontend timer
/// {
- bool hasFrontendTimer() const { return FrontendTimer != 0; }
+ bool hasFrontendTimer() const { return FrontendTimer.isValid(); }
llvm::Timer &getFrontendTimer() const {
assert(FrontendTimer && "Compiler instance has no frontend timer!");
diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
index c67be92472..fee8d95a05 100644
--- a/include/clang/Frontend/FrontendAction.h
+++ b/include/clang/Frontend/FrontendAction.h
@@ -116,7 +116,7 @@ public:
bool isCurrentFileAST() const {
assert(!CurrentInput.isEmpty() && "No current file!");
- return CurrentASTUnit != 0;
+ return CurrentASTUnit.isValid();
}
const FrontendInputFile &getCurrentInput() const {
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index c46c8ce6ef..498de09496 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -264,7 +264,7 @@ public:
/// \brief Checks whether the map exists or not.
bool HasIncludeAliasMap() const {
- return IncludeAliases;
+ return IncludeAliases.isValid();
}
/// \brief Map the source include name to the dest include name.
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h
index 64323b7c76..b4ce4db7dd 100644
--- a/include/clang/Lex/MacroInfo.h
+++ b/include/clang/Lex/MacroInfo.h
@@ -421,7 +421,7 @@ public:
bool isValid() const { return DefDirective != 0; }
bool isInvalid() const { return !isValid(); }
- operator bool() const { return isValid(); }
+ LLVM_EXPLICIT operator bool() const { return isValid(); }
inline DefInfo getPreviousDefinition(bool AllowHidden = false);
const DefInfo getPreviousDefinition(bool AllowHidden = false) const {
diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h
index 9fe97d0111..bd57ce4877 100644
--- a/include/clang/Lex/ModuleMap.h
+++ b/include/clang/Lex/ModuleMap.h
@@ -80,7 +80,7 @@ class ModuleMap {
// \brief Whether this known header is valid (i.e., it has an
// associated module).
- operator bool() const { return Storage.getPointer() != 0; }
+ LLVM_EXPLICIT operator bool() const { return Storage.getPointer() != 0; }
};
typedef llvm::DenseMap<const FileEntry *, KnownHeader> HeadersMap;
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index c5981777cd..89cb696f62 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -1400,7 +1400,7 @@ private:
bool InCachingLexMode() const {
// If the Lexer pointers are 0 and IncludeMacroStack is empty, it means
// that we are past EOF, not that we are in CachingLex mode.
- return CurPPLexer == 0 && CurTokenLexer == 0 && CurPTHLexer == 0 &&
+ return !CurPPLexer && !CurTokenLexer && !CurPTHLexer &&
!IncludeMacroStack.empty();
}
void EnterCachingLexMode();
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 72acacf5ae..1a1d6d2ae1 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -2138,9 +2138,18 @@ private:
//===--------------------------------------------------------------------===//
// OpenMP: Directives and clauses.
+ /// \brief Parses declarative OpenMP directives.
DeclGroupPtrTy ParseOpenMPDeclarativeDirective();
+ /// \brief Parses simple list of variables.
+ ///
+ /// \param Kind Kind of the directive.
+ /// \param [out] VarList List of referenced variables.
+ /// \param AllowScopeSpecifier true, if the variables can have fully
+ /// qualified names.
+ ///
bool ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
- SmallVectorImpl<DeclarationNameInfo> &IdList);
+ SmallVectorImpl<Expr *> &VarList,
+ bool AllowScopeSpecifier);
public:
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
bool AllowDestructorName,
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
index 58781ac628..727ceebe8b 100644
--- a/include/clang/Sema/Initialization.h
+++ b/include/clang/Sema/Initialization.h
@@ -706,6 +706,16 @@ public:
/// \brief Array must be initialized with an initializer list or a
/// string literal.
FK_ArrayNeedsInitListOrStringLiteral,
+ /// \brief Array must be initialized with an initializer list or a
+ /// wide string literal.
+ FK_ArrayNeedsInitListOrWideStringLiteral,
+ /// \brief Initializing a wide char array with narrow string literal.
+ FK_NarrowStringIntoWideCharArray,
+ /// \brief Initializing char array with wide string literal.
+ FK_WideStringIntoCharArray,
+ /// \brief Initializing wide char array with incompatible wide string
+ /// literal.
+ FK_IncompatWideStringIntoWideChar,
/// \brief Array type mismatch.
FK_ArrayTypeMismatch,
/// \brief Non-constant array initializer
@@ -841,7 +851,7 @@ public:
void setSequenceKind(enum SequenceKind SK) { SequenceKind = SK; }
/// \brief Determine whether the initialization sequence is valid.
- operator bool() const { return !Failed(); }
+ LLVM_EXPLICIT operator bool() const { return !Failed(); }
/// \brief Determine whether the initialization sequence is invalid.
bool Failed() const { return SequenceKind == FailedSequence; }
diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h
index c3d1f4e0b7..92c486db36 100644
--- a/include/clang/Sema/Ownership.h
+++ b/include/clang/Sema/Ownership.h
@@ -65,7 +65,7 @@ namespace clang {
Ptr = Traits::getAsVoidPointer(P);
}
- operator bool() const { return Ptr != 0; }
+ LLVM_EXPLICIT operator bool() const { return Ptr != 0; }
void *getAsOpaquePtr() const { return Ptr; }
static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); }
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 8e1ebd844e..61b91c5962 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -216,7 +216,7 @@ class Sema {
// it will keep having external linkage. If it has internal linkage, we
// will not link it. Since it has no previous decls, it will remain
// with internal linkage.
- return !Old->isHidden() || New->hasExternalLinkage();
+ return !Old->isHidden() || New->isExternallyVisible();
}
public:
@@ -5994,7 +5994,7 @@ public:
/// \brief Determines whether we have exceeded the maximum
/// recursive template instantiations.
- operator bool() const { return Invalid; }
+ LLVM_EXPLICIT operator bool() const { return Invalid; }
private:
Sema &SemaRef;
@@ -6682,16 +6682,19 @@ public:
unsigned SpellingListIndex, bool IsPackExpansion);
// OpenMP directives and clauses.
-
+ /// \brief Called on correct id-expression from the '#pragma omp
+ /// threadprivate'.
+ ExprResult ActOnOpenMPIdExpression(Scope *CurScope,
+ CXXScopeSpec &ScopeSpec,
+ const DeclarationNameInfo &Id);
/// \brief Called on well-formed '#pragma omp threadprivate'.
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(
- SourceLocation Loc,
- Scope *CurScope,
- ArrayRef<DeclarationNameInfo> IdList);
- /// \brief Build a new OpenMPThreadPrivateDecl and check its correctness.
+ SourceLocation Loc,
+ ArrayRef<Expr *> VarList);
+ // \brief Builds a new OpenMPThreadPrivateDecl and checks its correctness.
OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(
- SourceLocation Loc,
- ArrayRef<DeclRefExpr *> VarList);
+ SourceLocation Loc,
+ ArrayRef<Expr *> VarList);
/// \brief The kind of conversion being performed.
enum CheckedConversionKind {
diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h
index 5fbfba2d5d..59f3417605 100644
--- a/include/clang/Sema/TypoCorrection.h
+++ b/include/clang/Sema/TypoCorrection.h
@@ -140,7 +140,7 @@ public:
}
/// \brief Returns whether this TypoCorrection has a non-empty DeclarationName
- operator bool() const { return bool(CorrectionName); }
+ LLVM_EXPLICIT operator bool() const { return bool(CorrectionName); }
/// \brief Mark this TypoCorrection as being a keyword.
/// Since addCorrectionDeclsand setCorrectionDecl don't allow NULL to be
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index bb59784dff..073baf514c 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -1232,7 +1232,7 @@ public:
void setDeserializationListener(ASTDeserializationListener *Listener);
/// \brief Determine whether this AST reader has a global index.
- bool hasGlobalIndex() const { return GlobalIndex; }
+ bool hasGlobalIndex() const { return GlobalIndex.isValid(); }
/// \brief Attempts to load the global index.
///
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index a80b5a7a24..09ee005af7 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -504,7 +504,7 @@ public:
}
bool hasCallStackHint() {
- return (CallStackHint != 0);
+ return CallStackHint.isValid();
}
/// Produce the hint for the given node. The node contains
diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h
index 0dbaab033d..219e99cfd4 100644
--- a/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/include/clang/StaticAnalyzer/Core/Checker.h
@@ -502,10 +502,14 @@ struct ImplicitNullDerefEvent {
};
/// \brief A helper class which wraps a boolean value set to false by default.
+///
+/// This class should behave exactly like 'bool' except that it doesn't need to
+/// be explicitly initialized.
struct DefaultBool {
bool val;
DefaultBool() : val(false) {}
- operator bool() const { return val; }
+ /*implicit*/ operator bool&() { return val; }
+ /*implicit*/ operator const bool&() const { return val; }
DefaultBool &operator=(bool b) { val = b; return *this; }
};
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index b219495d5f..230ce1ea5c 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -231,7 +231,7 @@ public:
bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
SVal val);
- operator bool() { return First && Binding; }
+ LLVM_EXPLICIT operator bool() { return First && Binding; }
const MemRegion *getRegion() { return Binding; }
};
diff --git a/lib/ARCMigrate/TransUnbridgedCasts.cpp b/lib/ARCMigrate/TransUnbridgedCasts.cpp
index fc4a75fdb8..a5752f8157 100644
--- a/lib/ARCMigrate/TransUnbridgedCasts.cpp
+++ b/lib/ARCMigrate/TransUnbridgedCasts.cpp
@@ -148,7 +148,7 @@ private:
if (FD->getName() == "CFRetain" &&
FD->getNumParams() == 1 &&
FD->getParent()->isTranslationUnit() &&
- FD->hasExternalLinkage()) {
+ FD->isExternallyVisible()) {
Expr *Arg = callE->getArg(0);
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
const Expr *sub = ICE->getSubExpr();
@@ -413,7 +413,7 @@ private:
FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl()))
if (FD->getName() == "CFRetain" && FD->getNumParams() == 1 &&
FD->getParent()->isTranslationUnit() &&
- FD->hasExternalLinkage())
+ FD->isExternallyVisible())
return true;
return false;
diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp
index 087219535a..6c724af53a 100644
--- a/lib/ARCMigrate/Transforms.cpp
+++ b/lib/ARCMigrate/Transforms.cpp
@@ -94,7 +94,7 @@ bool trans::isPlusOne(const Expr *E) {
if (FD->isGlobal() &&
FD->getIdentifier() &&
FD->getParent()->isTranslationUnit() &&
- FD->hasExternalLinkage() &&
+ FD->isExternallyVisible() &&
ento::cocoa::isRefType(callE->getType(), "CF",
FD->getIdentifier()->getName())) {
StringRef fname = FD->getIdentifier()->getName();
@@ -198,7 +198,7 @@ bool trans::isGlobalVar(Expr *E) {
E = E->IgnoreParenCasts();
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
return DRE->getDecl()->getDeclContext()->isFileContext() &&
- DRE->getDecl()->hasExternalLinkage();
+ DRE->getDecl()->isExternallyVisible();
if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
return isGlobalVar(condOp->getTrueExpr()) &&
isGlobalVar(condOp->getFalseExpr());
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 986bb8c3d2..b19150f048 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -409,6 +409,8 @@ comments::FullComment *ASTContext::cloneFullComment(comments::FullComment *FC,
comments::FullComment *ASTContext::getCommentForDecl(
const Decl *D,
const Preprocessor *PP) const {
+ if (D->isInvalidDecl())
+ return NULL;
D = adjustDeclToTemplate(D);
const Decl *Canonical = D->getCanonicalDecl();
@@ -1343,8 +1345,28 @@ ASTContext::getTypeInfoDataSizeInChars(QualType T) const {
return sizeAndAlign;
}
+/// getConstantArrayInfoInChars - Performing the computation in CharUnits
+/// instead of in bits prevents overflowing the uint64_t for some large arrays.
+std::pair<CharUnits, CharUnits>
+static getConstantArrayInfoInChars(const ASTContext &Context,
+ const ConstantArrayType *CAT) {
+ std::pair<CharUnits, CharUnits> EltInfo =
+ Context.getTypeInfoInChars(CAT->getElementType());
+ uint64_t Size = CAT->getSize().getZExtValue();
+ assert((Size == 0 || static_cast<uint64_t>(EltInfo.first.getQuantity()) <=
+ (uint64_t)(-1)/Size) &&
+ "Overflow in array type char size evaluation");
+ uint64_t Width = EltInfo.first.getQuantity() * Size;
+ unsigned Align = EltInfo.second.getQuantity();
+ Width = llvm::RoundUpToAlignment(Width, Align);
+ return std::make_pair(CharUnits::fromQuantity(Width),
+ CharUnits::fromQuantity(Align));
+}
+
std::pair<CharUnits, CharUnits>
ASTContext::getTypeInfoInChars(const Type *T) const {
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T))
+ return getConstantArrayInfoInChars(*this, CAT);
std::pair<uint64_t, unsigned> Info = getTypeInfo(T);
return std::make_pair(toCharUnitsFromBits(Info.first),
toCharUnitsFromBits(Info.second));
@@ -1700,10 +1722,10 @@ int64_t ASTContext::toBits(CharUnits CharSize) const {
/// getTypeSizeInChars - Return the size of the specified type, in characters.
/// This method does not work on incomplete types.
CharUnits ASTContext::getTypeSizeInChars(QualType T) const {
- return toCharUnitsFromBits(getTypeSize(T));
+ return getTypeInfoInChars(T).first;
}
CharUnits ASTContext::getTypeSizeInChars(const Type *T) const {
- return toCharUnitsFromBits(getTypeSize(T));
+ return getTypeInfoInChars(T).first;
}
/// getTypeAlignInChars - Return the ABI-specified alignment of a type, in
@@ -7767,30 +7789,23 @@ QualType ASTContext::GetBuiltinType(unsigned Id,
}
GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) {
- GVALinkage External = GVA_StrongExternal;
-
- Linkage L = FD->getLinkage();
- switch (L) {
- case NoLinkage:
- case InternalLinkage:
- case UniqueExternalLinkage:
+ if (!FD->isExternallyVisible())
return GVA_Internal;
-
- case ExternalLinkage:
- switch (FD->getTemplateSpecializationKind()) {
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
- External = GVA_StrongExternal;
- break;
- case TSK_ExplicitInstantiationDefinition:
- return GVA_ExplicitTemplateInstantiation;
+ GVALinkage External = GVA_StrongExternal;
+ switch (FD->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ External = GVA_StrongExternal;
+ break;
+
+ case TSK_ExplicitInstantiationDefinition:
+ return GVA_ExplicitTemplateInstantiation;
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ImplicitInstantiation:
- External = GVA_TemplateInstantiation;
- break;
- }
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ImplicitInstantiation:
+ External = GVA_TemplateInstantiation;
+ break;
}
if (!FD->isInlined())
@@ -7820,6 +7835,9 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) {
}
GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
+ if (!VD->isExternallyVisible())
+ return GVA_Internal;
+
// If this is a static data member, compute the kind of template
// specialization. Otherwise, this variable is not part of a
// template.
@@ -7827,30 +7845,20 @@ GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
if (VD->isStaticDataMember())
TSK = VD->getTemplateSpecializationKind();
- Linkage L = VD->getLinkage();
+ switch (TSK) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ return GVA_StrongExternal;
- switch (L) {
- case NoLinkage:
- case InternalLinkage:
- case UniqueExternalLinkage:
- return GVA_Internal;
+ case TSK_ExplicitInstantiationDeclaration:
+ llvm_unreachable("Variable should not be instantiated");
+ // Fall through to treat this like any other instantiation.
- case ExternalLinkage:
- switch (TSK) {
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
- return GVA_StrongExternal;
+ case TSK_ExplicitInstantiationDefinition:
+ return GVA_ExplicitTemplateInstantiation;
- case TSK_ExplicitInstantiationDeclaration:
- llvm_unreachable("Variable should not be instantiated");
- // Fall through to treat this like any other instantiation.
-
- case TSK_ExplicitInstantiationDefinition:
- return GVA_ExplicitTemplateInstantiation;
-
- case TSK_ImplicitInstantiation:
- return GVA_TemplateInstantiation;
- }
+ case TSK_ImplicitInstantiation:
+ return GVA_TemplateInstantiation;
}
llvm_unreachable("Invalid Linkage!");
@@ -7986,7 +7994,8 @@ size_t ASTContext::getSideTableAllocatedMemory() const {
void ASTContext::addUnnamedTag(const TagDecl *Tag) {
// FIXME: This mangling should be applied to function local classes too
if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl() ||
- !isa<CXXRecordDecl>(Tag->getParent()) || Tag->getLinkage() != ExternalLinkage)
+ !isa<CXXRecordDecl>(Tag->getParent()) ||
+ !Tag->isExternallyVisible())
return;
std::pair<llvm::DenseMap<const DeclContext *, unsigned>::iterator, bool> P =
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 766a7a995b..e0f552ba67 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -300,8 +300,7 @@ void clang::FormatASTNodeDiagnosticArgument(
assert(ModLen == 0 && ArgLen == 0 &&
"Invalid modifier for DeclarationName argument");
- DeclarationName N = DeclarationName::getFromOpaqueInteger(Val);
- N.printName(OS);
+ OS << DeclarationName::getFromOpaqueInteger(Val);
break;
}
case DiagnosticsEngine::ak_nameddecl: {
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 340cc41f7e..cd974f0d02 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -449,9 +449,7 @@ void ASTDumper::dumpBareDeclRef(const Decl *D) {
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
ColorScope Color(*this, DeclNameColor);
- OS << " '";
- ND->getDeclName().printName(OS);
- OS << "'";
+ OS << " '" << ND->getDeclName() << '\'';
}
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
@@ -1331,7 +1329,7 @@ void ASTDumper::dumpStmt(const Stmt *S) {
return;
}
- setMoreChildren(S->children());
+ setMoreChildren(!S->children().empty());
ConstStmtVisitor<ASTDumper>::Visit(S);
setMoreChildren(false);
for (Stmt::const_child_range CI = S->children(); CI; ++CI) {
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 915eb6feb8..204b9d001c 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -2610,8 +2610,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
continue;
if (FunctionDecl *FoundFunction = dyn_cast<FunctionDecl>(FoundDecls[I])) {
- if (isExternalLinkage(FoundFunction->getLinkage()) &&
- isExternalLinkage(D->getLinkage())) {
+ if (FoundFunction->hasExternalFormalLinkage() &&
+ D->hasExternalFormalLinkage()) {
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundFunction->getType())) {
// FIXME: Actually try to merge the body and other attributes.
@@ -2878,7 +2878,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundField->getType(),
- Name)) {
+ !Name.isEmpty())) {
Importer.Imported(D, FoundField);
return FoundField;
}
@@ -2995,8 +2995,8 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
if (VarDecl *FoundVar = dyn_cast<VarDecl>(FoundDecls[I])) {
// We have found a variable that we may need to merge with. Check it.
- if (isExternalLinkage(FoundVar->getLinkage()) &&
- isExternalLinkage(D->getLinkage())) {
+ if (FoundVar->hasExternalFormalLinkage() &&
+ D->hasExternalFormalLinkage()) {
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundVar->getType())) {
MergeWithVar = FoundVar;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index ab9d73b917..b8f478728f 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -483,6 +483,10 @@ static bool isSingleLineExternC(const Decl &D) {
return false;
}
+static bool isExternalLinkage(Linkage L) {
+ return L == UniqueExternalLinkage || L == ExternalLinkage;
+}
+
static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
LVComputationKind computation) {
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
@@ -660,9 +664,20 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// this translation unit. However, we should use the C linkage
// rules instead for extern "C" declarations.
if (Context.getLangOpts().CPlusPlus &&
- !Function->isInExternCContext() &&
- Function->getType()->getLinkage() == UniqueExternalLinkage)
- return LinkageInfo::uniqueExternal();
+ !Function->isInExternCContext()) {
+ // Only look at the type-as-written. If this function has an auto-deduced
+ // return type, we can't compute the linkage of that type because it could
+ // require looking at the linkage of this function, and we don't need this
+ // for correctness because the type is not part of the function's
+ // signature.
+ // FIXME: This is a hack. We should be able to solve this circularity some
+ // other way.
+ QualType TypeAsWritten = Function->getType();
+ if (TypeSourceInfo *TSI = Function->getTypeSourceInfo())
+ TypeAsWritten = TSI->getType();
+ if (TypeAsWritten->getLinkage() == UniqueExternalLinkage)
+ return LinkageInfo::uniqueExternal();
+ }
// Consider LV from the template and the template arguments.
// We're at file scope, so we do not need to worry about nested
@@ -874,7 +889,7 @@ bool NamedDecl::isLinkageValid() const {
Linkage(CachedLinkage);
}
-Linkage NamedDecl::getLinkage() const {
+Linkage NamedDecl::getLinkageInternal() const {
if (HasCachedLinkage)
return Linkage(CachedLinkage);
@@ -1278,7 +1293,7 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
}
bool NamedDecl::hasLinkage() const {
- return getLinkage() != NoLinkage;
+ return getLinkageInternal() != NoLinkage;
}
NamedDecl *NamedDecl::getUnderlyingDeclImpl() {
@@ -1502,7 +1517,7 @@ template<typename T>
static LanguageLinkage getLanguageLinkageTemplate(const T &D) {
// C++ [dcl.link]p1: All function types, function names with external linkage,
// and variable names with external linkage have a language linkage.
- if (!isExternalLinkage(D.getLinkage()))
+ if (!D.hasExternalFormalLinkage())
return NoLanguageLinkage;
// Language linkage is a C++ concept, but saying that everything else in C has
@@ -2304,7 +2319,7 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const {
const FunctionDecl *Prev = this;
bool FoundBody = false;
while ((Prev = Prev->getPreviousDecl())) {
- FoundBody |= Prev->Body;
+ FoundBody |= Prev->Body.isValid();
if (Prev->Body) {
// If it's not the case that both 'inline' and 'extern' are
@@ -2332,7 +2347,7 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const {
const FunctionDecl *Prev = this;
bool FoundBody = false;
while ((Prev = Prev->getPreviousDecl())) {
- FoundBody |= Prev->Body;
+ FoundBody |= Prev->Body.isValid();
if (RedeclForcesDefC99(Prev))
return false;
}
diff --git a/lib/AST/DeclOpenMP.cpp b/lib/AST/DeclOpenMP.cpp
index c0d10a0f41..522caefe3b 100644
--- a/lib/AST/DeclOpenMP.cpp
+++ b/lib/AST/DeclOpenMP.cpp
@@ -28,9 +28,9 @@ void OMPThreadPrivateDecl::anchor() { }
OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C,
DeclContext *DC,
SourceLocation L,
- ArrayRef<DeclRefExpr *> VL) {
+ ArrayRef<Expr *> VL) {
unsigned Size = sizeof(OMPThreadPrivateDecl) +
- (VL.size() * sizeof(DeclRefExpr *));
+ (VL.size() * sizeof(Expr *));
void *Mem = C.Allocate(Size, llvm::alignOf<OMPThreadPrivateDecl>());
OMPThreadPrivateDecl *D = new (Mem) OMPThreadPrivateDecl(OMPThreadPrivate,
@@ -43,7 +43,7 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C,
OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C,
unsigned ID,
unsigned N) {
- unsigned Size = sizeof(OMPThreadPrivateDecl) + (N * sizeof(DeclRefExpr *));
+ unsigned Size = sizeof(OMPThreadPrivateDecl) + (N * sizeof(Expr *));
void *Mem = AllocateDeserializedDecl(C, ID, Size);
OMPThreadPrivateDecl *D = new (Mem) OMPThreadPrivateDecl(OMPThreadPrivate,
@@ -52,9 +52,9 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C,
return D;
}
-void OMPThreadPrivateDecl::setVars(ArrayRef<DeclRefExpr *> VL) {
+void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) {
assert(VL.size() == NumVars &&
"Number of variables is not the same as the preallocated buffer");
- DeclRefExpr **Vars = reinterpret_cast<DeclRefExpr **>(this + 1);
+ Expr **Vars = reinterpret_cast<Expr **>(this + 1);
std::copy(VL.begin(), VL.end(), Vars);
}
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index d47972bc61..1c9fd2d5f6 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -1180,9 +1180,9 @@ void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
if (!D->varlist_empty()) {
for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
E = D->varlist_end();
- I != E; ++I) {
+ I != E; ++I) {
Out << (I == D->varlist_begin() ? '(' : ',')
- << *cast<NamedDecl>((*I)->getDecl());
+ << *cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl());
}
Out << ")";
}
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index e4a41b6ffb..e064e23a0a 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -133,6 +133,66 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
llvm_unreachable("Invalid DeclarationName Kind!");
}
+raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {
+ switch (N.getNameKind()) {
+ case DeclarationName::Identifier:
+ if (const IdentifierInfo *II = N.getAsIdentifierInfo())
+ OS << II->getName();
+ return OS;
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ return OS << N.getObjCSelector().getAsString();
+
+ case DeclarationName::CXXConstructorName: {
+ QualType ClassType = N.getCXXNameType();
+ if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
+ return OS << *ClassRec->getDecl();
+ return OS << ClassType.getAsString();
+ }
+
+ case DeclarationName::CXXDestructorName: {
+ OS << '~';
+ QualType Type = N.getCXXNameType();
+ if (const RecordType *Rec = Type->getAs<RecordType>())
+ return OS << *Rec->getDecl();
+ return OS << Type.getAsString();
+ }
+
+ case DeclarationName::CXXOperatorName: {
+ static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
+ 0,
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ Spelling,
+#include "clang/Basic/OperatorKinds.def"
+ };
+ const char *OpName = OperatorNames[N.getCXXOverloadedOperator()];
+ assert(OpName && "not an overloaded operator");
+
+ OS << "operator";
+ if (OpName[0] >= 'a' && OpName[0] <= 'z')
+ OS << ' ';
+ return OS << OpName;
+ }
+
+ case DeclarationName::CXXLiteralOperatorName:
+ return OS << "operator \"\" " << N.getCXXLiteralIdentifier()->getName();
+
+ case DeclarationName::CXXConversionFunctionName: {
+ OS << "operator ";
+ QualType Type = N.getCXXNameType();
+ if (const RecordType *Rec = Type->getAs<RecordType>())
+ return OS << *Rec->getDecl();
+ return OS << Type.getAsString();
+ }
+ case DeclarationName::CXXUsingDirective:
+ return OS << "<using-directive>";
+ }
+
+ llvm_unreachable("Unexpected declaration name kind");
+}
+
} // end namespace clang
DeclarationName::NameKind DeclarationName::getNameKind() const {
@@ -180,80 +240,10 @@ bool DeclarationName::isDependentName() const {
std::string DeclarationName::getAsString() const {
std::string Result;
llvm::raw_string_ostream OS(Result);
- printName(OS);
+ OS << *this;
return OS.str();
}
-void DeclarationName::printName(raw_ostream &OS) const {
- switch (getNameKind()) {
- case Identifier:
- if (const IdentifierInfo *II = getAsIdentifierInfo())
- OS << II->getName();
- return;
-
- case ObjCZeroArgSelector:
- case ObjCOneArgSelector:
- case ObjCMultiArgSelector:
- OS << getObjCSelector().getAsString();
- return;
-
- case CXXConstructorName: {
- QualType ClassType = getCXXNameType();
- if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
- OS << *ClassRec->getDecl();
- else
- OS << ClassType.getAsString();
- return;
- }
-
- case CXXDestructorName: {
- OS << '~';
- QualType Type = getCXXNameType();
- if (const RecordType *Rec = Type->getAs<RecordType>())
- OS << *Rec->getDecl();
- else
- OS << Type.getAsString();
- return;
- }
-
- case CXXOperatorName: {
- static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
- 0,
-#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
- Spelling,
-#include "clang/Basic/OperatorKinds.def"
- };
- const char *OpName = OperatorNames[getCXXOverloadedOperator()];
- assert(OpName && "not an overloaded operator");
-
- OS << "operator";
- if (OpName[0] >= 'a' && OpName[0] <= 'z')
- OS << ' ';
- OS << OpName;
- return;
- }
-
- case CXXLiteralOperatorName:
- OS << "operator \"\" " << getCXXLiteralIdentifier()->getName();
- return;
-
- case CXXConversionFunctionName: {
- OS << "operator ";
- QualType Type = getCXXNameType();
- if (const RecordType *Rec = Type->getAs<RecordType>())
- OS << *Rec->getDecl();
- else
- OS << Type.getAsString();
- return;
- }
- case CXXUsingDirective:
- OS << "<using-directive>";
- return;
- }
-
- llvm_unreachable("Unexpected declaration name kind");
-}
-
QualType DeclarationName::getCXXNameType() const {
if (CXXSpecialName *CXXName = getAsCXXSpecialName())
return CXXName->Type;
@@ -336,8 +326,7 @@ DeclarationName DeclarationName::getUsingDirectiveName() {
}
void DeclarationName::dump() const {
- printName(llvm::errs());
- llvm::errs() << '\n';
+ llvm::errs() << *this << '\n';
}
DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
@@ -537,7 +526,7 @@ void DeclarationNameInfo::printName(raw_ostream &OS) const {
case DeclarationName::CXXOperatorName:
case DeclarationName::CXXLiteralOperatorName:
case DeclarationName::CXXUsingDirective:
- Name.printName(OS);
+ OS << Name;
return;
case DeclarationName::CXXConstructorName:
@@ -549,9 +538,8 @@ void DeclarationNameInfo::printName(raw_ostream &OS) const {
else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
OS << "operator ";
OS << TInfo->getType().getAsString();
- }
- else
- Name.printName(OS);
+ } else
+ OS << Name;
return;
}
llvm_unreachable("Unexpected declaration name kind");
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 15cf5ac4ab..f587dfa93e 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -423,7 +423,7 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
FoundD = 0;
std::size_t Size = sizeof(DeclRefExpr);
- if (QualifierLoc != 0)
+ if (QualifierLoc)
Size += sizeof(NestedNameSpecifierLoc);
if (FoundD)
Size += sizeof(NamedDecl *);
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index bf967961aa..3741bf12d5 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -1809,7 +1809,7 @@ struct CompleteObject {
assert(Value && "missing value for complete object");
}
- operator bool() const { return Value; }
+ LLVM_EXPLICIT operator bool() const { return Value; }
};
/// Find the designated sub-object of an rvalue.
@@ -2769,7 +2769,9 @@ enum EvalStmtResult {
/// Hit a 'continue' statement.
ESR_Continue,
/// Hit a 'break' statement.
- ESR_Break
+ ESR_Break,
+ /// Still scanning for 'case' or 'default' statement.
+ ESR_CaseNotFound
};
}
@@ -2803,12 +2805,13 @@ static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl,
}
static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
- const Stmt *S);
+ const Stmt *S, const SwitchCase *SC = 0);
/// Evaluate the body of a loop, and translate the result as appropriate.
static EvalStmtResult EvaluateLoopBody(APValue &Result, EvalInfo &Info,
- const Stmt *Body) {
- switch (EvalStmtResult ESR = EvaluateStmt(Result, Info, Body)) {
+ const Stmt *Body,
+ const SwitchCase *Case = 0) {
+ switch (EvalStmtResult ESR = EvaluateStmt(Result, Info, Body, Case)) {
case ESR_Break:
return ESR_Succeeded;
case ESR_Succeeded:
@@ -2816,17 +2819,127 @@ static EvalStmtResult EvaluateLoopBody(APValue &Result, EvalInfo &Info,
return ESR_Continue;
case ESR_Failed:
case ESR_Returned:
+ case ESR_CaseNotFound:
return ESR;
}
llvm_unreachable("Invalid EvalStmtResult!");
}
+/// Evaluate a switch statement.
+static EvalStmtResult EvaluateSwitch(APValue &Result, EvalInfo &Info,
+ const SwitchStmt *SS) {
+ // Evaluate the switch condition.
+ if (SS->getConditionVariable() &&
+ !EvaluateDecl(Info, SS->getConditionVariable()))
+ return ESR_Failed;
+ APSInt Value;
+ if (!EvaluateInteger(SS->getCond(), Value, Info))
+ return ESR_Failed;
+
+ // Find the switch case corresponding to the value of the condition.
+ // FIXME: Cache this lookup.
+ const SwitchCase *Found = 0;
+ for (const SwitchCase *SC = SS->getSwitchCaseList(); SC;
+ SC = SC->getNextSwitchCase()) {
+ if (isa<DefaultStmt>(SC)) {
+ Found = SC;
+ continue;
+ }
+
+ const CaseStmt *CS = cast<CaseStmt>(SC);
+ APSInt LHS = CS->getLHS()->EvaluateKnownConstInt(Info.Ctx);
+ APSInt RHS = CS->getRHS() ? CS->getRHS()->EvaluateKnownConstInt(Info.Ctx)
+ : LHS;
+ if (LHS <= Value && Value <= RHS) {
+ Found = SC;
+ break;
+ }
+ }
+
+ if (!Found)
+ return ESR_Succeeded;
+
+ // Search the switch body for the switch case and evaluate it from there.
+ switch (EvalStmtResult ESR = EvaluateStmt(Result, Info, SS->getBody(), Found)) {
+ case ESR_Break:
+ return ESR_Succeeded;
+ case ESR_Succeeded:
+ case ESR_Continue:
+ case ESR_Failed:
+ case ESR_Returned:
+ return ESR;
+ case ESR_CaseNotFound:
+ llvm_unreachable("couldn't find switch case");
+ }
+ llvm_unreachable("Invalid EvalStmtResult!");
+}
+
// Evaluate a statement.
static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
- const Stmt *S) {
+ const Stmt *S, const SwitchCase *Case) {
if (!Info.nextStep(S))
return ESR_Failed;
+ // If we're hunting down a 'case' or 'default' label, recurse through
+ // substatements until we hit the label.
+ if (Case) {
+ // FIXME: We don't start the lifetime of objects whose initialization we
+ // jump over. However, such objects must be of class type with a trivial
+ // default constructor that initialize all subobjects, so must be empty,
+ // so this almost never matters.
+ switch (S->getStmtClass()) {
+ case Stmt::CompoundStmtClass:
+ // FIXME: Precompute which substatement of a compound statement we
+ // would jump to, and go straight there rather than performing a
+ // linear scan each time.
+ case Stmt::LabelStmtClass:
+ case Stmt::AttributedStmtClass:
+ case Stmt::DoStmtClass:
+ break;
+
+ case Stmt::CaseStmtClass:
+ case Stmt::DefaultStmtClass:
+ if (Case == S)
+ Case = 0;
+ break;
+
+ case Stmt::IfStmtClass: {
+ // FIXME: Precompute which side of an 'if' we would jump to, and go
+ // straight there rather than scanning both sides.
+ const IfStmt *IS = cast<IfStmt>(S);
+ EvalStmtResult ESR = EvaluateStmt(Result, Info, IS->getThen(), Case);
+ if (ESR != ESR_CaseNotFound || !IS->getElse())
+ return ESR;
+ return EvaluateStmt(Result, Info, IS->getElse(), Case);
+ }
+
+ case Stmt::WhileStmtClass: {
+ EvalStmtResult ESR =
+ EvaluateLoopBody(Result, Info, cast<WhileStmt>(S)->getBody(), Case);
+ if (ESR != ESR_Continue)
+ return ESR;
+ break;
+ }
+
+ case Stmt::ForStmtClass: {
+ const ForStmt *FS = cast<ForStmt>(S);
+ EvalStmtResult ESR =
+ EvaluateLoopBody(Result, Info, FS->getBody(), Case);
+ if (ESR != ESR_Continue)
+ return ESR;
+ if (FS->getInc() && !EvaluateIgnoredValue(Info, FS->getInc()))
+ return ESR_Failed;
+ break;
+ }
+
+ case Stmt::DeclStmtClass:
+ // FIXME: If the variable has initialization that can't be jumped over,
+ // bail out of any immediately-surrounding compound-statement too.
+ default:
+ return ESR_CaseNotFound;
+ }
+ }
+
// FIXME: Mark all temporaries in the current frame as destroyed at
// the end of each full-expression.
switch (S->getStmtClass()) {
@@ -2865,11 +2978,13 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
const CompoundStmt *CS = cast<CompoundStmt>(S);
for (CompoundStmt::const_body_iterator BI = CS->body_begin(),
BE = CS->body_end(); BI != BE; ++BI) {
- EvalStmtResult ESR = EvaluateStmt(Result, Info, *BI);
- if (ESR != ESR_Succeeded)
+ EvalStmtResult ESR = EvaluateStmt(Result, Info, *BI, Case);
+ if (ESR == ESR_Succeeded)
+ Case = 0;
+ else if (ESR != ESR_CaseNotFound)
return ESR;
}
- return ESR_Succeeded;
+ return Case ? ESR_CaseNotFound : ESR_Succeeded;
}
case Stmt::IfStmtClass: {
@@ -2909,9 +3024,10 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
const DoStmt *DS = cast<DoStmt>(S);
bool Continue;
do {
- EvalStmtResult ESR = EvaluateLoopBody(Result, Info, DS->getBody());
+ EvalStmtResult ESR = EvaluateLoopBody(Result, Info, DS->getBody(), Case);
if (ESR != ESR_Continue)
return ESR;
+ Case = 0;
if (!EvaluateAsBooleanCondition(DS->getCond(), Continue, Info))
return ESR_Failed;
@@ -2983,11 +3099,27 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
return ESR_Succeeded;
}
+ case Stmt::SwitchStmtClass:
+ return EvaluateSwitch(Result, Info, cast<SwitchStmt>(S));
+
case Stmt::ContinueStmtClass:
return ESR_Continue;
case Stmt::BreakStmtClass:
return ESR_Break;
+
+ case Stmt::LabelStmtClass:
+ return EvaluateStmt(Result, Info, cast<LabelStmt>(S)->getSubStmt(), Case);
+
+ case Stmt::AttributedStmtClass:
+ // As a general principle, C++11 attributes can be ignored without
+ // any semantic impact.
+ return EvaluateStmt(Result, Info, cast<AttributedStmt>(S)->getSubStmt(),
+ Case);
+
+ case Stmt::CaseStmtClass:
+ case Stmt::DefaultStmtClass:
+ return EvaluateStmt(Result, Info, cast<SwitchCase>(S)->getSubStmt(), Case);
}
}
@@ -3029,6 +3161,11 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc,
Declaration->isConstexpr())
return false;
+ // Bail out with no diagnostic if the function declaration itself is invalid.
+ // We will have produced a relevant diagnostic while parsing it.
+ if (Declaration->isInvalidDecl())
+ return false;
+
// Can we evaluate this function call?
if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl())
return true;
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index d28aced172..3137f3c8fd 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -405,7 +405,7 @@ bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) {
if (DC->isFunctionOrMethod() && D->hasLinkage())
while (!DC->isNamespace() && !DC->isTranslationUnit())
DC = getEffectiveParentContext(DC);
- if (DC->isTranslationUnit() && D->getLinkage() != InternalLinkage)
+ if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage)
return false;
}
@@ -1053,7 +1053,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// static void foo();
// This naming convention is the same as that followed by GCC,
// though it shouldn't actually matter.
- if (ND && ND->getLinkage() == InternalLinkage &&
+ if (ND && ND->getFormalLinkage() == InternalLinkage &&
getEffectiveDeclContext(ND)->isFileContext())
Out << 'L';
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 7c797eef4d..d03060b391 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -22,6 +22,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/TargetInfo.h"
#include <map>
using namespace clang;
@@ -58,19 +59,27 @@ class MicrosoftCXXNameMangler {
ASTContext &getASTContext() const { return Context.getASTContext(); }
+ // FIXME: If we add support for __ptr32/64 qualifiers, then we should push
+ // this check into mangleQualifiers().
+ const bool PointersAre64Bit;
+
public:
enum QualifierMangleMode { QMM_Drop, QMM_Mangle, QMM_Escape, QMM_Result };
MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_)
: Context(C), Out(Out_),
Structor(0), StructorType(-1),
- UseNameBackReferences(true) { }
+ UseNameBackReferences(true),
+ PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
+ 64) { }
MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_,
const CXXDestructorDecl *D, CXXDtorType Type)
: Context(C), Out(Out_),
Structor(getStructor(D)), StructorType(Type),
- UseNameBackReferences(true) { }
+ UseNameBackReferences(true),
+ PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
+ 64) { }
raw_ostream &getStream() const { return Out; }
@@ -199,7 +208,7 @@ bool MicrosoftMangleContext::shouldMangleDeclName(const NamedDecl *D) {
// Variables at global scope with internal linkage are not mangled.
if (!FD) {
const DeclContext *DC = D->getDeclContext();
- if (DC->isTranslationUnit() && D->getLinkage() == InternalLinkage)
+ if (DC->isTranslationUnit() && D->getFormalLinkage() == InternalLinkage)
return false;
}
@@ -1228,32 +1237,36 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
}
void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
- // <function-class> ::= A # private: near
- // ::= B # private: far
- // ::= C # private: static near
- // ::= D # private: static far
- // ::= E # private: virtual near
- // ::= F # private: virtual far
- // ::= G # private: thunk near
- // ::= H # private: thunk far
- // ::= I # protected: near
- // ::= J # protected: far
- // ::= K # protected: static near
- // ::= L # protected: static far
- // ::= M # protected: virtual near
- // ::= N # protected: virtual far
- // ::= O # protected: thunk near
- // ::= P # protected: thunk far
- // ::= Q # public: near
- // ::= R # public: far
- // ::= S # public: static near
- // ::= T # public: static far
- // ::= U # public: virtual near
- // ::= V # public: virtual far
- // ::= W # public: thunk near
- // ::= X # public: thunk far
- // ::= Y # global near
- // ::= Z # global far
+ // <function-class> ::= <member-function> E? # E designates a 64-bit 'this'
+ // # pointer. in 64-bit mode *all*
+ // # 'this' pointers are 64-bit.
+ // ::= <global-function>
+ // <member-function> ::= A # private: near
+ // ::= B # private: far
+ // ::= C # private: static near
+ // ::= D # private: static far
+ // ::= E # private: virtual near
+ // ::= F # private: virtual far
+ // ::= G # private: thunk near
+ // ::= H # private: thunk far
+ // ::= I # protected: near
+ // ::= J # protected: far
+ // ::= K # protected: static near
+ // ::= L # protected: static far
+ // ::= M # protected: virtual near
+ // ::= N # protected: virtual far
+ // ::= O # protected: thunk near
+ // ::= P # protected: thunk far
+ // ::= Q # public: near
+ // ::= R # public: far
+ // ::= S # public: static near
+ // ::= T # public: static far
+ // ::= U # public: virtual near
+ // ::= V # public: virtual far
+ // ::= W # public: thunk near
+ // ::= X # public: thunk far
+ // <global-function> ::= Y # global near
+ // ::= Z # global far
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
switch (MD->getAccess()) {
default:
@@ -1281,6 +1294,8 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
else
Out << 'Q';
}
+ if (PointersAre64Bit && !MD->isStatic())
+ Out << 'E';
} else
Out << 'Y';
}
@@ -1380,9 +1395,9 @@ void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
// <type> ::= <array-type>
// <array-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
// [Y <dimension-count> <dimension>+]
-// <element-type> # as global
-// ::= Q <cvr-qualifiers> [Y <dimension-count> <dimension>+]
-// <element-type> # as param
+// <element-type> # as global, E is never required
+// ::= Q E? <cvr-qualifiers> [Y <dimension-count> <dimension>+]
+// <element-type> # as param, E is required for 64-bit
// It's supposed to be the other way around, but for some strange reason, it
// isn't. Today this behavior is retained for the sole purpose of backwards
// compatibility.
@@ -1394,6 +1409,8 @@ void MicrosoftCXXNameMangler::mangleDecayedArrayType(const ArrayType *T,
manglePointerQualifiers(T->getElementType().getQualifiers());
} else {
Out << 'Q';
+ if (PointersAre64Bit)
+ Out << 'E';
}
mangleType(T->getElementType(), SourceRange());
}
@@ -1494,10 +1511,13 @@ void MicrosoftCXXNameMangler::mangleType(
}
// <type> ::= <pointer-type>
-// <pointer-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
+// <pointer-type> ::= E? <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
+// # the E is required for 64-bit non static pointers
void MicrosoftCXXNameMangler::mangleType(const PointerType *T,
SourceRange Range) {
QualType PointeeTy = T->getPointeeType();
+ if (PointersAre64Bit && !T->getPointeeType()->isFunctionType())
+ Out << 'E';
mangleType(PointeeTy, Range);
}
void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
@@ -1508,18 +1528,24 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
}
// <type> ::= <reference-type>
-// <reference-type> ::= A <cvr-qualifiers> <type>
+// <reference-type> ::= A E? <cvr-qualifiers> <type>
+// # the E is required for 64-bit non static lvalue references
void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T,
SourceRange Range) {
Out << 'A';
+ if (PointersAre64Bit && !T->getPointeeType()->isFunctionType())
+ Out << 'E';
mangleType(T->getPointeeType(), Range);
}
// <type> ::= <r-value-reference-type>
-// <r-value-reference-type> ::= $$Q <cvr-qualifiers> <type>
+// <r-value-reference-type> ::= $$Q E? <cvr-qualifiers> <type>
+// # the E is required for 64-bit non static rvalue references
void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T,
SourceRange Range) {
Out << "$$Q";
+ if (PointersAre64Bit && !T->getPointeeType()->isFunctionType())
+ Out << 'E';
mangleType(T->getPointeeType(), Range);
}
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 42c3ba31bc..eb39d08424 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -211,7 +211,7 @@ void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD,
if (!RD->isEmpty())
return;
- // If we have empty structures inside an union, we can assign both
+ // If we have empty structures inside a union, we can assign both
// the same offset. Just avoid pushing them twice in the list.
ClassVectorTy& Classes = EmptyClassOffsets[Offset];
if (std::find(Classes.begin(), Classes.end(), RD) != Classes.end())
@@ -2354,7 +2354,7 @@ static const CXXMethodDecl *computeKeyFunction(ASTContext &Context,
// A class that is not externally visible doesn't have a key function. (Or
// at least, there's no point to assigning a key function to such a class;
// this doesn't affect the ABI.)
- if (RD->getLinkage() != ExternalLinkage)
+ if (!RD->isExternallyVisible())
return 0;
// Template instantiations don't have key functions,see Itanium C++ ABI 5.2.6.
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index a1f0b08494..eacf367818 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -2124,7 +2124,7 @@ static CachedProperties computeCachedProperties(const Type *T) {
// - it is a class or enumeration type that is named (or has a name
// for linkage purposes (7.1.3)) and the name has linkage; or
// - it is a specialization of a class template (14); or
- Linkage L = Tag->getLinkage();
+ Linkage L = Tag->getLinkageInternal();
bool IsLocalOrUnnamed =
Tag->getDeclContext()->isFunctionOrMethod() ||
!Tag->hasNameForLinkage();
@@ -2166,7 +2166,7 @@ static CachedProperties computeCachedProperties(const Type *T) {
return result;
}
case Type::ObjCInterface: {
- Linkage L = cast<ObjCInterfaceType>(T)->getDecl()->getLinkage();
+ Linkage L = cast<ObjCInterfaceType>(T)->getDecl()->getLinkageInternal();
return CachedProperties(L, false);
}
case Type::ObjCObject:
diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp
index 6ebd736e3c..eccc9cd4d3 100644
--- a/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -744,6 +744,14 @@ void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
new TypeLocMatcher(NodeMatch), Action));
}
+bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
+ MatchCallback *Action) {
+ MatcherCallbackPairs.push_back(std::make_pair(NodeMatch.clone(), Action));
+ // TODO: Do runtime type checking to make sure the matcher is one of the valid
+ // top-level matchers.
+ return true;
+}
+
ASTConsumer *MatchFinder::newASTConsumer() {
return new internal::MatchASTConsumer(&MatcherCallbackPairs, ParsingDone);
}
diff --git a/lib/ASTMatchers/CMakeLists.txt b/lib/ASTMatchers/CMakeLists.txt
index 86560d61c9..4a390a8fc3 100644
--- a/lib/ASTMatchers/CMakeLists.txt
+++ b/lib/ASTMatchers/CMakeLists.txt
@@ -1,3 +1,5 @@
+add_subdirectory(Dynamic)
+
set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangASTMatchers
diff --git a/lib/ASTMatchers/Dynamic/CMakeLists.txt b/lib/ASTMatchers/Dynamic/CMakeLists.txt
new file mode 100644
index 0000000000..843341b297
--- /dev/null
+++ b/lib/ASTMatchers/Dynamic/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangDynamicASTMatchers
+ Diagnostics.cpp
+ VariantValue.cpp
+ Parser.cpp
+ Registry.cpp
+ )
+
+add_dependencies(clangDynamicASTMatchers
+ clangASTMatchers
+ )
+
+target_link_libraries(clangDynamicASTMatchers
+ clangASTMatchers
+ )
diff --git a/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/lib/ASTMatchers/Dynamic/Diagnostics.cpp
new file mode 100644
index 0000000000..fb3cac370f
--- /dev/null
+++ b/lib/ASTMatchers/Dynamic/Diagnostics.cpp
@@ -0,0 +1,113 @@
+//===--- Diagnostics.cpp - Helper class for error diagnostics -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+Diagnostics::ArgStream &
+Diagnostics::ArgStream::operator<<(const Twine &Arg) {
+ Out->push_back(Arg.str());
+ return *this;
+}
+
+Diagnostics::ArgStream Diagnostics::pushErrorFrame(const SourceRange &Range,
+ ErrorType Error) {
+ Frames.insert(Frames.begin(), ErrorFrame());
+ ErrorFrame &Last = Frames.front();
+ Last.Range = Range;
+ Last.Type = Error;
+ ArgStream Out = { &Last.Args };
+ return Out;
+}
+
+StringRef ErrorTypeToString(Diagnostics::ErrorType Type) {
+ switch (Type) {
+ case Diagnostics::ET_RegistryNotFound:
+ return "Matcher not found: $0";
+ case Diagnostics::ET_RegistryWrongArgCount:
+ return "Incorrect argument count. (Expected = $0) != (Actual = $1)";
+ case Diagnostics::ET_RegistryWrongArgType:
+ return "Incorrect type on function $0 for arg $1.";
+
+ case Diagnostics::ET_ParserStringError:
+ return "Error parsing string token: <$0>";
+ case Diagnostics::ET_ParserMatcherArgFailure:
+ return "Error parsing argument $0 for matcher $1.";
+ case Diagnostics::ET_ParserMatcherFailure:
+ return "Error building matcher $0.";
+ case Diagnostics::ET_ParserNoOpenParen:
+ return "Error parsing matcher. Found token <$0> while looking for '('.";
+ case Diagnostics::ET_ParserNoCloseParen:
+ return "Error parsing matcher. Found end-of-code while looking for ')'.";
+ case Diagnostics::ET_ParserNoComma:
+ return "Error parsing matcher. Found token <$0> while looking for ','.";
+ case Diagnostics::ET_ParserNoCode:
+ return "End of code found while looking for token.";
+ case Diagnostics::ET_ParserNotAMatcher:
+ return "Input value is not a matcher expression.";
+ case Diagnostics::ET_ParserInvalidToken:
+ return "Invalid token <$0> found when looking for a value.";
+
+ case Diagnostics::ET_None:
+ return "<N/A>";
+ }
+ llvm_unreachable("Unknown ErrorType value.");
+}
+
+std::string FormatErrorString(StringRef FormatString,
+ ArrayRef<std::string> Args) {
+ std::string Out;
+ while (!FormatString.empty()) {
+ std::pair<StringRef, StringRef> Pieces = FormatString.split("$");
+ Out += Pieces.first.str();
+ if (Pieces.second.empty()) break;
+
+ const char Next = Pieces.second.front();
+ FormatString = Pieces.second.drop_front();
+ if (Next >= '0' && Next <= '9') {
+ const unsigned Index = Next - '0';
+ if (Index < Args.size()) {
+ Out += Args[Index];
+ } else {
+ Out += "<Argument_Not_Provided>";
+ }
+ }
+ }
+ return Out;
+}
+
+std::string Diagnostics::ErrorFrame::ToString() const {
+ StringRef FormatString = ErrorTypeToString(Type);
+ std::string ErrorOut = FormatErrorString(FormatString, Args);
+ if (Range.Start.Line > 0 && Range.Start.Column > 0)
+ return (Twine(Range.Start.Line) + ":" + Twine(Range.Start.Column) + ": " +
+ ErrorOut).str();
+ return ErrorOut;
+}
+
+std::string Diagnostics::ToString() const {
+ if (Frames.empty()) return "";
+ return Frames[Frames.size() - 1].ToString();
+}
+
+std::string Diagnostics::ToStringFull() const {
+ std::string Result;
+ for (size_t i = 0, end = Frames.size(); i != end; ++i) {
+ if (i > 0) Result += "\n";
+ Result += Frames[i].ToString();
+ }
+ return Result;
+}
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
diff --git a/lib/ASTMatchers/Dynamic/Makefile b/lib/ASTMatchers/Dynamic/Makefile
new file mode 100644
index 0000000000..a57d752229
--- /dev/null
+++ b/lib/ASTMatchers/Dynamic/Makefile
@@ -0,0 +1,13 @@
+##===- clang/lib/ASTMatchers/Dynamic/Makefile --------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL := ../../..
+LIBRARYNAME := clangDynamicASTMatchers
+
+include $(CLANG_LEVEL)/Makefile
diff --git a/lib/ASTMatchers/Dynamic/Marshallers.h b/lib/ASTMatchers/Dynamic/Marshallers.h
new file mode 100644
index 0000000000..e75a175738
--- /dev/null
+++ b/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -0,0 +1,223 @@
+//===--- Marshallers.h - Generic matcher function marshallers -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Functions templates and classes to wrap matcher construct functions.
+///
+/// A collection of template function and classes that provide a generic
+/// marshalling layer on top of matcher construct functions.
+/// These are used by the registry to export all marshaller constructors with
+/// the same generic interface.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H
+
+#include <list>
+#include <string>
+#include <vector>
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/type_traits.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+namespace internal {
+
+/// \brief Helper template class to just from argument type to the right is/get
+/// functions in VariantValue.
+/// Used to verify and extract the matcher arguments below.
+template <class T> struct ArgTypeTraits;
+template <class T> struct ArgTypeTraits<const T &> : public ArgTypeTraits<T> {
+};
+
+template <> struct ArgTypeTraits<std::string> {
+ static bool is(const VariantValue &Value) { return Value.isString(); }
+ static const std::string &get(const VariantValue &Value) {
+ return Value.getString();
+ }
+};
+
+template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > {
+ static bool is(const VariantValue &Value) { return Value.isMatcher(); }
+ static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) {
+ return Value.getTypedMatcher<T>();
+ }
+
+};
+
+/// \brief Generic MatcherCreate interface.
+///
+/// Provides a \c run() method that constructs the matcher from the provided
+/// arguments.
+class MatcherCreateCallback {
+public:
+ virtual ~MatcherCreateCallback() {}
+ virtual DynTypedMatcher *run(const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const = 0;
+};
+
+/// \brief Simple callback implementation. Marshaller and function are provided.
+///
+/// \param Marshaller Function to unpack the arguments and call \c Func
+/// \param Func Matcher construct function. This is the function that
+/// compile-time matcher expressions would use to create the matcher.
+template <typename MarshallerType, typename FuncType>
+class FixedArgCountMatcherCreateCallback : public MatcherCreateCallback {
+public:
+ FixedArgCountMatcherCreateCallback(MarshallerType Marshaller, FuncType Func,
+ StringRef MatcherName)
+ : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName.str()) {}
+
+ DynTypedMatcher *run(const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args, Diagnostics *Error) const {
+ return Marshaller(Func, MatcherName, NameRange, Args, Error);
+ }
+
+private:
+ const MarshallerType Marshaller;
+ const FuncType Func;
+ const std::string MatcherName;
+};
+
+/// \brief Helper function to do template argument deduction.
+template <typename MarshallerType, typename FuncType>
+MatcherCreateCallback *
+createMarshallerCallback(MarshallerType Marshaller, FuncType Func,
+ StringRef MatcherName) {
+ return new FixedArgCountMatcherCreateCallback<MarshallerType, FuncType>(
+ Marshaller, Func, MatcherName);
+}
+
+/// \brief Helper macros to check the arguments on all marshaller functions.
+#define CHECK_ARG_COUNT(count) \
+ if (Args.size() != count) { \
+ Error->pushErrorFrame(NameRange, Error->ET_RegistryWrongArgCount) \
+ << count << Args.size(); \
+ return NULL; \
+ }
+
+#define CHECK_ARG_TYPE(index, type) \
+ if (!ArgTypeTraits<type>::is(Args[index].Value)) { \
+ Error->pushErrorFrame(Args[index].Range, Error->ET_RegistryWrongArgType) \
+ << MatcherName << (index + 1); \
+ return NULL; \
+ }
+
+/// \brief Metafunction to normalize argument types.
+///
+/// We need to remove the const& out of the function parameters to be able to
+/// find values on VariantValue.
+template <typename T>
+struct remove_const_ref :
+ public llvm::remove_const<typename llvm::remove_reference<T>::type> {
+};
+
+/// \brief 0-arg marshaller function.
+template <typename ReturnType>
+DynTypedMatcher *matcherMarshall0(ReturnType (*Func)(), StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) {
+ CHECK_ARG_COUNT(0);
+ return Func().clone();
+}
+
+/// \brief 1-arg marshaller function.
+template <typename ReturnType, typename InArgType1>
+DynTypedMatcher *matcherMarshall1(ReturnType (*Func)(InArgType1),
+ StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) {
+ typedef typename remove_const_ref<InArgType1>::type ArgType1;
+ CHECK_ARG_COUNT(1);
+ CHECK_ARG_TYPE(0, ArgType1);
+ return Func(ArgTypeTraits<ArgType1>::get(Args[0].Value)).clone();
+}
+
+/// \brief Variadic marshaller function.
+template <typename BaseType, typename DerivedType>
+class VariadicMatcherCreateCallback : public MatcherCreateCallback {
+public:
+ explicit VariadicMatcherCreateCallback(StringRef MatcherName)
+ : MatcherName(MatcherName.str()) {}
+
+ typedef ast_matchers::internal::Matcher<DerivedType> DerivedMatcherType;
+
+ DynTypedMatcher *run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const {
+ std::list<DerivedMatcherType> References;
+ std::vector<const DerivedMatcherType *> InnerArgs(Args.size());
+ for (size_t i = 0, e = Args.size(); i != e; ++i) {
+ CHECK_ARG_TYPE(i, DerivedMatcherType);
+ References.push_back(
+ ArgTypeTraits<DerivedMatcherType>::get(Args[i].Value));
+ InnerArgs[i] = &References.back();
+ }
+ return ast_matchers::internal::makeDynCastAllOfComposite<BaseType>(
+ ArrayRef<const DerivedMatcherType *>(InnerArgs)).clone();
+ }
+
+private:
+ const std::string MatcherName;
+};
+
+#undef CHECK_ARG_COUNT
+#undef CHECK_ARG_TYPE
+
+/// Helper functions to select the appropriate marshaller functions.
+/// They detects the number of arguments, arguments types and return type.
+
+/// \brief 0-arg overload
+template <typename ReturnType>
+MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(),
+ StringRef MatcherName) {
+ return createMarshallerCallback(matcherMarshall0<ReturnType>, Func,
+ MatcherName);
+}
+
+/// \brief 1-arg overload
+template <typename ReturnType, typename ArgType1>
+MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1),
+ StringRef MatcherName) {
+ return createMarshallerCallback(matcherMarshall1<ReturnType, ArgType1>, Func,
+ MatcherName);
+}
+
+/// \brief Variadic overload.
+template <typename MatcherType>
+MatcherCreateCallback *makeMatcherAutoMarshall(
+ ast_matchers::internal::VariadicAllOfMatcher<MatcherType> Func,
+ StringRef MatcherName) {
+ return new VariadicMatcherCreateCallback<MatcherType, MatcherType>(
+ MatcherName);
+}
+
+template <typename BaseType, typename MatcherType>
+MatcherCreateCallback *
+makeMatcherAutoMarshall(ast_matchers::internal::VariadicDynCastAllOfMatcher<
+ BaseType, MatcherType> Func,
+ StringRef MatcherName) {
+ return new VariadicMatcherCreateCallback<BaseType, MatcherType>(MatcherName);
+}
+
+} // namespace internal
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H
diff --git a/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp
new file mode 100644
index 0000000000..1678820da0
--- /dev/null
+++ b/lib/ASTMatchers/Dynamic/Parser.cpp
@@ -0,0 +1,332 @@
+//===--- Parser.cpp - Matcher expression parser -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Recursive parser implementation for the matcher expression grammar.
+///
+//===----------------------------------------------------------------------===//
+
+#include <string>
+#include <vector>
+
+#include "clang/ASTMatchers/Dynamic/Parser.h"
+#include "clang/ASTMatchers/Dynamic/Registry.h"
+#include "clang/Basic/CharInfo.h"
+#include "llvm/ADT/Twine.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+/// \brief Simple structure to hold information for one token from the parser.
+struct Parser::TokenInfo {
+ /// \brief Different possible tokens.
+ enum TokenKind {
+ TK_Eof = 0,
+ TK_OpenParen = 1,
+ TK_CloseParen = 2,
+ TK_Comma = 3,
+ TK_Literal = 4,
+ TK_Ident = 5,
+ TK_InvalidChar = 6,
+ TK_Error = 7
+ };
+
+ TokenInfo() : Text(), Kind(TK_Eof), Range(), Value() {}
+
+ StringRef Text;
+ TokenKind Kind;
+ SourceRange Range;
+ VariantValue Value;
+};
+
+/// \brief Simple tokenizer for the parser.
+class Parser::CodeTokenizer {
+public:
+ explicit CodeTokenizer(StringRef MatcherCode, Diagnostics *Error)
+ : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error) {
+ NextToken = getNextToken();
+ }
+
+ /// \brief Returns but doesn't consume the next token.
+ const TokenInfo &peekNextToken() const { return NextToken; }
+
+ /// \brief Consumes and returns the next token.
+ TokenInfo consumeNextToken() {
+ TokenInfo ThisToken = NextToken;
+ NextToken = getNextToken();
+ return ThisToken;
+ }
+
+ TokenInfo::TokenKind nextTokenKind() const { return NextToken.Kind; }
+
+private:
+ TokenInfo getNextToken() {
+ consumeWhitespace();
+ TokenInfo Result;
+ Result.Range.Start = currentLocation();
+
+ if (Code.empty()) {
+ Result.Kind = TokenInfo::TK_Eof;
+ Result.Text = "";
+ return Result;
+ }
+
+ switch (Code[0]) {
+ case ',':
+ Result.Kind = TokenInfo::TK_Comma;
+ Result.Text = Code.substr(0, 1);
+ Code = Code.drop_front();
+ break;
+ case '(':
+ Result.Kind = TokenInfo::TK_OpenParen;
+ Result.Text = Code.substr(0, 1);
+ Code = Code.drop_front();
+ break;
+ case ')':
+ Result.Kind = TokenInfo::TK_CloseParen;
+ Result.Text = Code.substr(0, 1);
+ Code = Code.drop_front();
+ break;
+
+ case '"':
+ case '\'':
+ // Parse a string literal.
+ consumeStringLiteral(&Result);
+ break;
+
+ default:
+ if (isAlphanumeric(Code[0])) {
+ // Parse an identifier
+ size_t TokenLength = 1;
+ while (TokenLength < Code.size() && isAlphanumeric(Code[TokenLength]))
+ ++TokenLength;
+ Result.Kind = TokenInfo::TK_Ident;
+ Result.Text = Code.substr(0, TokenLength);
+ Code = Code.drop_front(TokenLength);
+ } else {
+ Result.Kind = TokenInfo::TK_InvalidChar;
+ Result.Text = Code.substr(0, 1);
+ Code = Code.drop_front(1);
+ }
+ break;
+ }
+
+ Result.Range.End = currentLocation();
+ return Result;
+ }
+
+ /// \brief Consume a string literal.
+ ///
+ /// \c Code must be positioned at the start of the literal (the opening
+ /// quote). Consumed until it finds the same closing quote character.
+ void consumeStringLiteral(TokenInfo *Result) {
+ bool InEscape = false;
+ const char Marker = Code[0];
+ for (size_t Length = 1, Size = Code.size(); Length != Size; ++Length) {
+ if (InEscape) {
+ InEscape = false;
+ continue;
+ }
+ if (Code[Length] == '\\') {
+ InEscape = true;
+ continue;
+ }
+ if (Code[Length] == Marker) {
+ Result->Kind = TokenInfo::TK_Literal;
+ Result->Text = Code.substr(0, Length + 1);
+ Result->Value = Code.substr(1, Length - 1).str();
+ Code = Code.drop_front(Length + 1);
+ return;
+ }
+ }
+
+ StringRef ErrorText = Code;
+ Code = Code.drop_front(Code.size());
+ SourceRange Range;
+ Range.Start = Result->Range.Start;
+ Range.End = currentLocation();
+ Error->pushErrorFrame(Range, Error->ET_ParserStringError)
+ << ErrorText;
+ Result->Kind = TokenInfo::TK_Error;
+ }
+
+ /// \brief Consume all leading whitespace from \c Code.
+ void consumeWhitespace() {
+ while (!Code.empty() && isWhitespace(Code[0])) {
+ if (Code[0] == '\n') {
+ ++Line;
+ StartOfLine = Code.drop_front();
+ }
+ Code = Code.drop_front();
+ }
+ }
+
+ SourceLocation currentLocation() {
+ SourceLocation Location;
+ Location.Line = Line;
+ Location.Column = Code.data() - StartOfLine.data() + 1;
+ return Location;
+ }
+
+ StringRef Code;
+ StringRef StartOfLine;
+ unsigned Line;
+ Diagnostics *Error;
+ TokenInfo NextToken;
+};
+
+Parser::Sema::~Sema() {}
+
+/// \brief Parse and validate a matcher expression.
+/// \return \c true on success, in which case \c Value has the matcher parsed.
+/// If the input is malformed, or some argument has an error, it
+/// returns \c false.
+bool Parser::parseMatcherExpressionImpl(VariantValue *Value) {
+ const TokenInfo NameToken = Tokenizer->consumeNextToken();
+ assert(NameToken.Kind == TokenInfo::TK_Ident);
+ const TokenInfo OpenToken = Tokenizer->consumeNextToken();
+ if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
+ Error->pushErrorFrame(OpenToken.Range, Error->ET_ParserNoOpenParen)
+ << OpenToken.Text;
+ return false;
+ }
+
+ std::vector<ParserValue> Args;
+ TokenInfo EndToken;
+ while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
+ if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
+ // End of args.
+ EndToken = Tokenizer->consumeNextToken();
+ break;
+ }
+ if (Args.size() > 0) {
+ // We must find a , token to continue.
+ const TokenInfo CommaToken = Tokenizer->consumeNextToken();
+ if (CommaToken.Kind != TokenInfo::TK_Comma) {
+ Error->pushErrorFrame(CommaToken.Range, Error->ET_ParserNoComma)
+ << CommaToken.Text;
+ return false;
+ }
+ }
+
+ ParserValue ArgValue;
+ ArgValue.Text = Tokenizer->peekNextToken().Text;
+ ArgValue.Range = Tokenizer->peekNextToken().Range;
+ if (!parseExpressionImpl(&ArgValue.Value)) {
+ Error->pushErrorFrame(NameToken.Range,
+ Error->ET_ParserMatcherArgFailure)
+ << (Args.size() + 1) << NameToken.Text;
+ return false;
+ }
+
+ Args.push_back(ArgValue);
+ }
+
+ if (EndToken.Kind == TokenInfo::TK_Eof) {
+ Error->pushErrorFrame(OpenToken.Range, Error->ET_ParserNoCloseParen);
+ return false;
+ }
+
+ // Merge the start and end infos.
+ SourceRange MatcherRange = NameToken.Range;
+ MatcherRange.End = EndToken.Range.End;
+ DynTypedMatcher *Result =
+ S->actOnMatcherExpression(NameToken.Text, MatcherRange, Args, Error);
+ if (Result == NULL) {
+ Error->pushErrorFrame(NameToken.Range, Error->ET_ParserMatcherFailure)
+ << NameToken.Text;
+ return false;
+ }
+
+ Value->takeMatcher(Result);
+ return true;
+}
+
+/// \brief Parse an <Expresssion>
+bool Parser::parseExpressionImpl(VariantValue *Value) {
+ switch (Tokenizer->nextTokenKind()) {
+ case TokenInfo::TK_Literal:
+ *Value = Tokenizer->consumeNextToken().Value;
+ return true;
+
+ case TokenInfo::TK_Ident:
+ return parseMatcherExpressionImpl(Value);
+
+ case TokenInfo::TK_Eof:
+ Error->pushErrorFrame(Tokenizer->consumeNextToken().Range,
+ Error->ET_ParserNoCode);
+ return false;
+
+ case TokenInfo::TK_Error:
+ // This error was already reported by the tokenizer.
+ return false;
+
+ case TokenInfo::TK_OpenParen:
+ case TokenInfo::TK_CloseParen:
+ case TokenInfo::TK_Comma:
+ case TokenInfo::TK_InvalidChar:
+ const TokenInfo Token = Tokenizer->consumeNextToken();
+ Error->pushErrorFrame(Token.Range, Error->ET_ParserInvalidToken)
+ << Token.Text;
+ return false;
+ }
+
+ llvm_unreachable("Unknown token kind.");
+}
+
+Parser::Parser(CodeTokenizer *Tokenizer, Sema *S,
+ Diagnostics *Error)
+ : Tokenizer(Tokenizer), S(S), Error(Error) {}
+
+class RegistrySema : public Parser::Sema {
+public:
+ virtual ~RegistrySema() {}
+ DynTypedMatcher *actOnMatcherExpression(StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) {
+ return Registry::constructMatcher(MatcherName, NameRange, Args, Error);
+ }
+};
+
+bool Parser::parseExpression(StringRef Code, VariantValue *Value,
+ Diagnostics *Error) {
+ RegistrySema S;
+ return parseExpression(Code, &S, Value, Error);
+}
+
+bool Parser::parseExpression(StringRef Code, Sema *S,
+ VariantValue *Value, Diagnostics *Error) {
+ CodeTokenizer Tokenizer(Code, Error);
+ return Parser(&Tokenizer, S, Error).parseExpressionImpl(Value);
+}
+
+DynTypedMatcher *Parser::parseMatcherExpression(StringRef Code,
+ Diagnostics *Error) {
+ RegistrySema S;
+ return parseMatcherExpression(Code, &S, Error);
+}
+
+DynTypedMatcher *Parser::parseMatcherExpression(StringRef Code,
+ Parser::Sema *S,
+ Diagnostics *Error) {
+ VariantValue Value;
+ if (!parseExpression(Code, S, &Value, Error))
+ return NULL;
+ if (!Value.isMatcher()) {
+ Error->pushErrorFrame(SourceRange(), Error->ET_ParserNotAMatcher);
+ return NULL;
+ }
+ return Value.getMatcher().clone();
+}
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
new file mode 100644
index 0000000000..53e90f1c77
--- /dev/null
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -0,0 +1,153 @@
+//===--- Registry.cpp - Matcher registry ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Registry map populated at static initialization time.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTMatchers/Dynamic/Registry.h"
+
+#include <utility>
+
+#include "Marshallers.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ManagedStatic.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+namespace {
+
+using internal::MatcherCreateCallback;
+
+typedef llvm::StringMap<const MatcherCreateCallback *> ConstructorMap;
+class RegistryMaps {
+public:
+ RegistryMaps();
+ ~RegistryMaps();
+
+ const ConstructorMap &constructors() const { return Constructors; }
+
+private:
+ void registerMatcher(StringRef MatcherName, MatcherCreateCallback *Callback);
+ ConstructorMap Constructors;
+};
+
+void RegistryMaps::registerMatcher(StringRef MatcherName,
+ MatcherCreateCallback *Callback) {
+ Constructors[MatcherName] = Callback;
+}
+
+#define REGISTER_MATCHER(name) \
+ registerMatcher(#name, internal::makeMatcherAutoMarshall( \
+ ::clang::ast_matchers::name, #name));
+
+/// \brief Generate a registry map with all the known matchers.
+RegistryMaps::RegistryMaps() {
+ // TODO: This list is not complete. It only has non-overloaded matchers,
+ // which are the simplest to add to the system. Overloaded matchers require
+ // more supporting code that was omitted from the first revision for
+ // simplicitly of code review.
+
+ REGISTER_MATCHER(binaryOperator);
+ REGISTER_MATCHER(bindTemporaryExpr);
+ REGISTER_MATCHER(boolLiteral);
+ REGISTER_MATCHER(callExpr);
+ REGISTER_MATCHER(characterLiteral);
+ REGISTER_MATCHER(compoundStmt);
+ REGISTER_MATCHER(conditionalOperator);
+ REGISTER_MATCHER(constCastExpr);
+ REGISTER_MATCHER(constructExpr);
+ REGISTER_MATCHER(constructorDecl);
+ REGISTER_MATCHER(declRefExpr);
+ REGISTER_MATCHER(declStmt);
+ REGISTER_MATCHER(defaultArgExpr);
+ REGISTER_MATCHER(doStmt);
+ REGISTER_MATCHER(dynamicCastExpr);
+ REGISTER_MATCHER(explicitCastExpr);
+ REGISTER_MATCHER(expr);
+ REGISTER_MATCHER(fieldDecl);
+ REGISTER_MATCHER(forStmt);
+ REGISTER_MATCHER(functionDecl);
+ REGISTER_MATCHER(hasAnyParameter);
+ REGISTER_MATCHER(hasAnySubstatement);
+ REGISTER_MATCHER(hasConditionVariableStatement);
+ REGISTER_MATCHER(hasDestinationType);
+ REGISTER_MATCHER(hasEitherOperand);
+ REGISTER_MATCHER(hasFalseExpression);
+ REGISTER_MATCHER(hasImplicitDestinationType);
+ REGISTER_MATCHER(hasInitializer);
+ REGISTER_MATCHER(hasLHS);
+ REGISTER_MATCHER(hasName);
+ REGISTER_MATCHER(hasObjectExpression);
+ REGISTER_MATCHER(hasRHS);
+ REGISTER_MATCHER(hasSourceExpression);
+ REGISTER_MATCHER(hasTrueExpression);
+ REGISTER_MATCHER(hasUnaryOperand);
+ REGISTER_MATCHER(ifStmt);
+ REGISTER_MATCHER(implicitCastExpr);
+ REGISTER_MATCHER(integerLiteral);
+ REGISTER_MATCHER(isArrow);
+ REGISTER_MATCHER(isConstQualified);
+ REGISTER_MATCHER(isImplicit);
+ REGISTER_MATCHER(member);
+ REGISTER_MATCHER(memberExpr);
+ REGISTER_MATCHER(methodDecl);
+ REGISTER_MATCHER(namedDecl);
+ REGISTER_MATCHER(newExpr);
+ REGISTER_MATCHER(ofClass);
+ REGISTER_MATCHER(on);
+ REGISTER_MATCHER(onImplicitObjectArgument);
+ REGISTER_MATCHER(operatorCallExpr);
+ REGISTER_MATCHER(recordDecl);
+ REGISTER_MATCHER(reinterpretCastExpr);
+ REGISTER_MATCHER(staticCastExpr);
+ REGISTER_MATCHER(stmt);
+ REGISTER_MATCHER(stringLiteral);
+ REGISTER_MATCHER(switchCase);
+ REGISTER_MATCHER(to);
+ REGISTER_MATCHER(unaryOperator);
+ REGISTER_MATCHER(varDecl);
+ REGISTER_MATCHER(whileStmt);
+}
+
+RegistryMaps::~RegistryMaps() {
+ for (ConstructorMap::iterator it = Constructors.begin(),
+ end = Constructors.end();
+ it != end; ++it) {
+ delete it->second;
+ }
+}
+
+static llvm::ManagedStatic<RegistryMaps> RegistryData;
+
+} // anonymous namespace
+
+// static
+DynTypedMatcher *Registry::constructMatcher(StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) {
+ ConstructorMap::const_iterator it =
+ RegistryData->constructors().find(MatcherName);
+ if (it == RegistryData->constructors().end()) {
+ Error->pushErrorFrame(NameRange, Error->ET_RegistryNotFound)
+ << MatcherName;
+ return NULL;
+ }
+
+ return it->second->run(NameRange, Args, Error);
+}
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
diff --git a/lib/ASTMatchers/Dynamic/VariantValue.cpp b/lib/ASTMatchers/Dynamic/VariantValue.cpp
new file mode 100644
index 0000000000..e310fbfc58
--- /dev/null
+++ b/lib/ASTMatchers/Dynamic/VariantValue.cpp
@@ -0,0 +1,105 @@
+//===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Polymorphic value type.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
+ *this = Other;
+}
+
+VariantValue::VariantValue(const DynTypedMatcher &Matcher) : Type(VT_Nothing) {
+ setMatcher(Matcher);
+}
+
+VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
+ setString(String);
+}
+
+VariantValue::~VariantValue() { reset(); }
+
+VariantValue &VariantValue::operator=(const VariantValue &Other) {
+ if (this == &Other) return *this;
+ reset();
+ switch (Other.Type) {
+ case VT_String:
+ setString(Other.getString());
+ break;
+ case VT_Matcher:
+ setMatcher(Other.getMatcher());
+ break;
+ case VT_Nothing:
+ Type = VT_Nothing;
+ break;
+ }
+ return *this;
+}
+
+void VariantValue::reset() {
+ switch (Type) {
+ case VT_String:
+ delete Value.String;
+ break;
+ case VT_Matcher:
+ delete Value.Matcher;
+ break;
+ // Cases that do nothing.
+ case VT_Nothing:
+ break;
+ }
+ Type = VT_Nothing;
+}
+
+bool VariantValue::isString() const {
+ return Type == VT_String;
+}
+
+const std::string &VariantValue::getString() const {
+ assert(isString());
+ return *Value.String;
+}
+
+void VariantValue::setString(const std::string &NewValue) {
+ reset();
+ Type = VT_String;
+ Value.String = new std::string(NewValue);
+}
+
+bool VariantValue::isMatcher() const {
+ return Type == VT_Matcher;
+}
+
+const DynTypedMatcher &VariantValue::getMatcher() const {
+ assert(isMatcher());
+ return *Value.Matcher;
+}
+
+void VariantValue::setMatcher(const DynTypedMatcher &NewValue) {
+ reset();
+ Type = VT_Matcher;
+ Value.Matcher = NewValue.clone();
+}
+
+void VariantValue::takeMatcher(DynTypedMatcher *NewValue) {
+ reset();
+ Type = VT_Matcher;
+ Value.Matcher = NewValue;
+}
+
+} // end namespace dynamic
+} // end namespace ast_matchers
+} // end namespace clang
diff --git a/lib/ASTMatchers/Makefile b/lib/ASTMatchers/Makefile
index 76d82719a1..3ee9ccb580 100644
--- a/lib/ASTMatchers/Makefile
+++ b/lib/ASTMatchers/Makefile
@@ -10,4 +10,6 @@
CLANG_LEVEL := ../..
LIBRARYNAME := clangASTMatchers
+PARALLEL_DIRS = Dynamic
+
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 096c7a080b..6eb84ce92c 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -155,7 +155,7 @@ public:
return !(*this == rhs);
}
- operator bool() const {
+ LLVM_EXPLICIT operator bool() const {
return *this != const_iterator();
}
diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp
index 835908d2a1..b90fbc7a7c 100644
--- a/lib/Basic/OpenMPKinds.cpp
+++ b/lib/Basic/OpenMPKinds.cpp
@@ -32,7 +32,7 @@ const char *clang::getOpenMPDirectiveName(OpenMPDirectiveKind Kind) {
assert(Kind < NUM_OPENMP_DIRECTIVES);
switch (Kind) {
case OMPD_unknown:
- return ("unknown");
+ return "unknown";
#define OPENMP_DIRECTIVE(Name) \
case OMPD_##Name : return #Name;
#include "clang/Basic/OpenMPKinds.def"
@@ -41,3 +41,4 @@ const char *clang::getOpenMPDirectiveName(OpenMPDirectiveKind Kind) {
}
llvm_unreachable("Invalid OpenMP directive kind");
}
+
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 638d6a028c..6b376b30ad 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -3527,6 +3527,34 @@ class ARMTargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
+ static bool shouldUseInlineAtomic(const llvm::Triple &T) {
+ // On linux, binaries targeting old cpus call functions in libgcc to
+ // perform atomic operations. The implementation in libgcc then calls into
+ // the kernel which on armv6 and newer uses ldrex and strex. The net result
+ // is that if we assume the kernel is at least as recent as the hardware,
+ // it is safe to use atomic instructions on armv6 and newer.
+ if (T.getOS() != llvm::Triple::Linux)
+ return false;
+ StringRef ArchName = T.getArchName();
+ if (T.getArch() == llvm::Triple::arm) {
+ if (!ArchName.startswith("armv"))
+ return false;
+ StringRef VersionStr = ArchName.substr(4);
+ unsigned Version;
+ if (VersionStr.getAsInteger(10, Version))
+ return false;
+ return Version >= 6;
+ }
+ assert(T.getArch() == llvm::Triple::thumb);
+ if (!ArchName.startswith("thumbv"))
+ return false;
+ StringRef VersionStr = ArchName.substr(6);
+ unsigned Version;
+ if (VersionStr.getAsInteger(10, Version))
+ return false;
+ return Version >= 7;
+ }
+
public:
ARMTargetInfo(const std::string &TripleStr)
: TargetInfo(TripleStr), ABI("aapcs-linux"), CPU("arm1136j-s"), IsAAPCS(true)
@@ -3559,8 +3587,9 @@ public:
TheCXXABI.set(TargetCXXABI::GenericARM);
// ARM has atomics up to 8 bytes
- // FIXME: Set MaxAtomicInlineWidth if we have the feature v6e
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ MaxAtomicPromoteWidth = 64;
+ if (shouldUseInlineAtomic(getTriple()))
+ MaxAtomicInlineWidth = 64;
// Do force alignment of members that follow zero length bitfields. If
// the alignment of the zero-length bitfield is greater than the member
@@ -4275,6 +4304,11 @@ public:
// FIXME: Support Sparc quad-precision long double?
DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
"i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32:64-S128";
+ // This is an LP64 platform.
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+ IntMaxType = SignedLong;
+ UIntMaxType = UnsignedLong;
+ Int64Type = SignedLong;
}
virtual void getTargetDefines(const LangOptions &Opts,
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index d18767897f..bd5afb6d17 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -1645,11 +1645,10 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
if (BuiltinID == ARM::BI__clear_cache) {
+ assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments");
const FunctionDecl *FD = E->getDirectCallee();
- // Oddly people write this call without args on occasion and gcc accepts
- // it - it's also marked as varargs in the description file.
SmallVector<Value*, 2> Ops;
- for (unsigned i = 0; i < E->getNumArgs(); i++)
+ for (unsigned i = 0; i < 2; i++)
Ops.push_back(EmitScalarExpr(E->getArg(i)));
llvm::Type *Ty = CGM.getTypes().ConvertType(FD->getType());
llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty);
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 7d5d260304..f6ad8f2cc5 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -1220,9 +1220,11 @@ CollectTemplateParams(const TemplateParameterList *TPList,
V = CGM.GetAddrOfGlobalVar(VD);
// Member function pointers have special support for building them, though
// this is currently unsupported in LLVM CodeGen.
- if (InstanceMember)
+ if (InstanceMember) {
if (const CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(D))
V = CGM.getCXXABI().EmitMemberPointer(method);
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ V = CGM.GetAddrOfFunction(FD);
// Member data pointers have special handling too to compute the fixed
// offset within the object.
if (isa<FieldDecl>(D)) {
@@ -2172,8 +2174,21 @@ llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,
}
llvm::DIDescriptor CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
- if (const TypeDecl *RD = dyn_cast<TypeDecl>(D))
- return CreatePointeeType(QualType(RD->getTypeForDecl(), 0), llvm::DIFile());
+ // We only need a declaration (not a definition) of the type - so use whatever
+ // we would otherwise do to get a type for a pointee. (forward declarations in
+ // limited debug info, full definitions (if the type definition is available)
+ // in unlimited debug info)
+ if (const TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
+ llvm::DIFile DefUnit = getOrCreateFile(TD->getLocation());
+ return CreatePointeeType(CGM.getContext().getTypeDeclType(TD), DefUnit);
+ }
+ // Otherwise fall back to a fairly rudimentary cache of existing declarations.
+ // This doesn't handle providing declarations (for functions or variables) for
+ // entities without definitions in this TU, nor when the definition proceeds
+ // the call to this function.
+ // FIXME: This should be split out into more specific maps with support for
+ // emitting forward declarations and merging definitions with declarations,
+ // the same way as we do for types.
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator I =
DeclCache.find(D->getCanonicalDecl());
if (I == DeclCache.end())
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index e61a50eeb4..f221a0cd3e 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -95,6 +95,8 @@ class CGDebugInfo {
llvm::DenseMap<const char *, llvm::WeakVH> DIFileCache;
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH> SPCache;
+ /// \brief Cache declarations relevant to DW_TAG_imported_declarations (C++
+ /// using declarations) that aren't covered by other more specific caches.
llvm::DenseMap<const Decl *, llvm::WeakVH> DeclCache;
llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH> NameSpaceCache;
llvm::DenseMap<const Decl *, llvm::WeakVH> StaticDataMemberCache;
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 069cd5f9e7..9a345cf472 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -719,7 +719,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
/// Note that we only call this at the end of the translation unit.
llvm::GlobalVariable::LinkageTypes
CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
- if (RD->getLinkage() != ExternalLinkage)
+ if (!RD->isExternallyVisible())
return llvm::GlobalVariable::InternalLinkage;
// We're at the end of the translation unit, so the current key
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 6caf1689a9..5a7c305c64 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -2422,7 +2422,7 @@ public:
return ConstantEmission(C, false);
}
- operator bool() const { return ValueAndIsReference.getOpaqueValue() != 0; }
+ LLVM_EXPLICIT operator bool() const { return ValueAndIsReference.getOpaqueValue() != 0; }
bool isReference() const { return ValueAndIsReference.getInt(); }
LValue getReferenceLValue(CodeGenFunction &CGF, Expr *refExpr) const {
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 695048e5b3..0736879037 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1763,7 +1763,7 @@ void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D,
return;
// Must have internal linkage and an ordinary name.
- if (!D->getIdentifier() || D->getLinkage() != InternalLinkage)
+ if (!D->getIdentifier() || D->getFormalLinkage() != InternalLinkage)
return;
// Must be in an extern "C" context. Entities declared directly within
diff --git a/lib/CodeGen/CodeGenTBAA.cpp b/lib/CodeGen/CodeGenTBAA.cpp
index 5ff1560a48..3f0eaee536 100644
--- a/lib/CodeGen/CodeGenTBAA.cpp
+++ b/lib/CodeGen/CodeGenTBAA.cpp
@@ -162,8 +162,7 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
// on their mangled names, if they're external.
// TODO: Is there a way to get a program-wide unique name for a
// decl with local linkage or no linkage?
- if (Features.CPlusPlus &&
- ETy->getDecl()->getLinkage() != ExternalLinkage)
+ if (Features.CPlusPlus && !ETy->getDecl()->isExternallyVisible())
return MetadataCache[Ty] = getChar();
// TODO: This is using the RTTI name. Is there a better way to get
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 9a320f94bd..9fd8ac6916 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -19,11 +19,9 @@
#include "TokenAnnotator.h"
#include "UnwrappedLineParser.h"
#include "WhitespaceManager.h"
-#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/OperatorPrecedence.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Format/Format.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Allocator.h"
@@ -36,11 +34,21 @@ namespace llvm {
namespace yaml {
template <>
struct ScalarEnumerationTraits<clang::format::FormatStyle::LanguageStandard> {
- static void enumeration(IO &io,
- clang::format::FormatStyle::LanguageStandard &value) {
- io.enumCase(value, "C++03", clang::format::FormatStyle::LS_Cpp03);
- io.enumCase(value, "C++11", clang::format::FormatStyle::LS_Cpp11);
- io.enumCase(value, "Auto", clang::format::FormatStyle::LS_Auto);
+ static void enumeration(IO &IO,
+ clang::format::FormatStyle::LanguageStandard &Value) {
+ IO.enumCase(Value, "C++03", clang::format::FormatStyle::LS_Cpp03);
+ IO.enumCase(Value, "C++11", clang::format::FormatStyle::LS_Cpp11);
+ IO.enumCase(Value, "Auto", clang::format::FormatStyle::LS_Auto);
+ }
+};
+
+template <>
+struct ScalarEnumerationTraits<clang::format::FormatStyle::BraceBreakingStyle> {
+ static void
+ enumeration(IO &IO, clang::format::FormatStyle::BraceBreakingStyle &Value) {
+ IO.enumCase(Value, "Attach", clang::format::FormatStyle::BS_Attach);
+ IO.enumCase(Value, "Linux", clang::format::FormatStyle::BS_Linux);
+ IO.enumCase(Value, "Stroustrup", clang::format::FormatStyle::BS_Stroustrup);
}
};
@@ -85,6 +93,9 @@ template <> struct MappingTraits<clang::format::FormatStyle> {
IO.mapOptional("SpacesBeforeTrailingComments",
Style.SpacesBeforeTrailingComments);
IO.mapOptional("Standard", Style.Standard);
+ IO.mapOptional("IndentWidth", Style.IndentWidth);
+ IO.mapOptional("UseTab", Style.UseTab);
+ IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
}
};
}
@@ -111,6 +122,9 @@ FormatStyle getLLVMStyle() {
LLVMStyle.PointerBindsToType = false;
LLVMStyle.SpacesBeforeTrailingComments = 1;
LLVMStyle.Standard = FormatStyle::LS_Cpp03;
+ LLVMStyle.IndentWidth = 2;
+ LLVMStyle.UseTab = false;
+ LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
return LLVMStyle;
}
@@ -132,6 +146,9 @@ FormatStyle getGoogleStyle() {
GoogleStyle.PointerBindsToType = true;
GoogleStyle.SpacesBeforeTrailingComments = 2;
GoogleStyle.Standard = FormatStyle::LS_Auto;
+ GoogleStyle.IndentWidth = 2;
+ GoogleStyle.UseTab = false;
+ GoogleStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
return GoogleStyle;
}
@@ -185,7 +202,7 @@ std::string configurationAsText(const FormatStyle &Style) {
// reference here.
FormatStyle NonConstStyle = Style;
Output << NonConstStyle;
- return Text;
+ return Stream.str();
}
// Returns the length of everything up to the first possible line break after
@@ -267,7 +284,7 @@ private:
AvoidBinPacking(AvoidBinPacking), BreakBeforeParameter(false),
NoLineBreak(NoLineBreak), ColonPos(0), StartOfFunctionCall(0),
NestedNameSpecifierContinuation(0), CallContinuation(0),
- VariablePos(0) {}
+ VariablePos(0), ForFakeParenthesis(false) {}
/// \brief The position to which a specific parenthesis level needs to be
/// indented.
@@ -326,6 +343,13 @@ private:
/// Used to align further variables if necessary.
unsigned VariablePos;
+ /// \brief \c true if this \c ParenState was created for a fake parenthesis.
+ ///
+ /// Does not need to be considered for memoization / the comparison function
+ /// as otherwise identical states will have the same fake/non-fake
+ /// \c ParenStates.
+ bool ForFakeParenthesis;
+
bool operator<(const ParenState &Other) const {
if (Indent != Other.Indent)
return Indent < Other.Indent;
@@ -429,7 +453,7 @@ private:
if (Newline) {
unsigned WhitespaceStartColumn = State.Column;
if (Current.is(tok::r_brace)) {
- State.Column = Line.Level * 2;
+ State.Column = Line.Level * Style.IndentWidth;
} else if (Current.is(tok::string_literal) &&
State.StartOfStringLiteral != 0) {
State.Column = State.StartOfStringLiteral;
@@ -480,6 +504,8 @@ private:
!State.Stack.back().AvoidBinPacking) ||
Previous.Type == TT_BinaryOperator)
State.Stack.back().BreakBeforeParameter = false;
+ if (Previous.Type == TT_TemplateCloser && State.ParenLevel == 0)
+ State.Stack.back().BreakBeforeParameter = false;
if (!DryRun) {
unsigned NewLines = 1;
@@ -507,6 +533,7 @@ private:
}
const AnnotatedToken *TokenBefore = Current.getPreviousNoneComment();
if (TokenBefore && !TokenBefore->isOneOf(tok::comma, tok::semi) &&
+ TokenBefore->Type != TT_TemplateCloser &&
TokenBefore->Type != TT_BinaryOperator && !TokenBefore->opensScope())
State.Stack.back().BreakBeforeParameter = true;
@@ -517,7 +544,8 @@ private:
if (State.Stack.back().AvoidBinPacking) {
// If we are breaking after '(', '{', '<', this is not bin packing
// unless AllowAllParametersOfDeclarationOnNextLine is false.
- if ((Previous.isNot(tok::l_paren) && Previous.isNot(tok::l_brace)) ||
+ if (!(Previous.isOneOf(tok::l_paren, tok::l_brace) ||
+ Previous.Type == TT_BinaryOperator) ||
(!Style.AllowAllParametersOfDeclarationOnNextLine &&
Line.MustBeDeclaration))
State.Stack.back().BreakBeforeParameter = true;
@@ -604,6 +632,11 @@ private:
Current.LastInChainOfCalls ? 0 : State.Column +
Current.FormatTok.TokenLength;
if (Current.Type == TT_CtorInitializerColon) {
+ // Indent 2 from the column, so:
+ // SomeClass::SomeClass()
+ // : First(...), ...
+ // Next(...)
+ // ^ line up here.
State.Stack.back().Indent = State.Column + 2;
if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
State.Stack.back().AvoidBinPacking = true;
@@ -633,6 +666,7 @@ private:
E = Current.FakeLParens.rend();
I != E; ++I) {
ParenState NewParenState = State.Stack.back();
+ NewParenState.ForFakeParenthesis = true;
NewParenState.Indent =
std::max(std::max(State.Column, NewParenState.Indent),
State.Stack.back().LastSpace);
@@ -654,27 +688,31 @@ private:
// prepare for the following tokens.
if (Current.opensScope()) {
unsigned NewIndent;
+ unsigned LastSpace = State.Stack.back().LastSpace;
bool AvoidBinPacking;
if (Current.is(tok::l_brace)) {
- NewIndent = 2 + State.Stack.back().LastSpace;
+ NewIndent = Style.IndentWidth + LastSpace;
AvoidBinPacking = false;
} else {
- NewIndent = 4 + std::max(State.Stack.back().LastSpace,
- State.Stack.back().StartOfFunctionCall);
+ NewIndent =
+ 4 + std::max(LastSpace, State.Stack.back().StartOfFunctionCall);
AvoidBinPacking = !Style.BinPackParameters;
}
- State.Stack.push_back(
- ParenState(NewIndent, State.Stack.back().LastSpace, AvoidBinPacking,
- State.Stack.back().NoLineBreak));
if (Current.NoMoreTokensOnLevel && Current.FakeLParens.empty()) {
// This parenthesis was the last token possibly making use of Indent and
- // LastSpace of the next higher ParenLevel. Thus, erase them to acieve
+ // LastSpace of the next higher ParenLevel. Thus, erase them to achieve
// better memoization results.
- State.Stack[State.Stack.size() - 2].Indent = 0;
- State.Stack[State.Stack.size() - 2].LastSpace = 0;
+ for (unsigned i = State.Stack.size() - 1; i > 0; --i) {
+ State.Stack[i].Indent = 0;
+ State.Stack[i].LastSpace = 0;
+ if (!State.Stack[i].ForFakeParenthesis)
+ break;
+ }
}
+ State.Stack.push_back(ParenState(NewIndent, LastSpace, AvoidBinPacking,
+ State.Stack.back().NoLineBreak));
++State.ParenLevel;
}
@@ -702,10 +740,10 @@ private:
State.Stack.back().VariablePos = VariablePos;
}
- if (Current.is(tok::string_literal)) {
+ if (Current.is(tok::string_literal) && State.StartOfStringLiteral == 0) {
State.StartOfStringLiteral = State.Column;
- } else if (Current.isNot(tok::comment)) {
- State.StartOfStringLiteral = 0;
+ } else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash,
+ tok::string_literal)) {
}
State.Column += Current.FormatTok.TokenLength;
@@ -720,10 +758,18 @@ private:
/// \brief If the current token sticks out over the end of the line, break
/// it if possible.
+ ///
+ /// \returns An extra penalty if a token was broken, otherwise 0.
+ ///
+ /// Note that the penalty of the token protruding the allowed line length is
+ /// already handled in \c addNextStateToQueue; the returned penalty will only
+ /// cover the cost of the additional line breaks.
unsigned breakProtrudingToken(const AnnotatedToken &Current, LineState &State,
- bool DryRun) {
+ bool DryRun,
+ unsigned UnbreakableTailLength = 0) {
llvm::OwningPtr<BreakableToken> Token;
- unsigned StartColumn = State.Column - Current.FormatTok.TokenLength;
+ unsigned StartColumn = State.Column - Current.FormatTok.TokenLength -
+ UnbreakableTailLength;
if (Current.is(tok::string_literal)) {
// Only break up default narrow strings.
const char *LiteralData = SourceMgr.getCharacterData(
@@ -744,42 +790,55 @@ private:
Current.Parent->Type != TT_ImplicitStringLiteral)) {
Token.reset(new BreakableLineComment(SourceMgr, Current, StartColumn));
} else {
- return 0;
+ // If a token that we cannot breaks protrudes, it means we were unable to
+ // break a sequence of tokens due to disallowed breaks between the tokens.
+ // Thus, we recursively search backwards to try to find a breakable token.
+ if (State.Column <= getColumnLimit() ||
+ Current.CanBreakBefore || !Current.Parent)
+ return 0;
+ return breakProtrudingToken(
+ *Current.Parent, State, DryRun,
+ UnbreakableTailLength + Current.FormatTok.TokenLength);
}
+ if (UnbreakableTailLength >= getColumnLimit())
+ return 0;
+ unsigned RemainingSpace = getColumnLimit() - UnbreakableTailLength;
bool BreakInserted = false;
unsigned Penalty = 0;
+ unsigned PositionAfterLastLineInToken = 0;
for (unsigned LineIndex = 0; LineIndex < Token->getLineCount();
++LineIndex) {
unsigned TailOffset = 0;
- unsigned RemainingLength =
+ unsigned RemainingTokenLength =
Token->getLineLengthAfterSplit(LineIndex, TailOffset);
- while (RemainingLength > getColumnLimit()) {
+ while (RemainingTokenLength > RemainingSpace) {
BreakableToken::Split Split =
- Token->getSplit(LineIndex, TailOffset, getColumnLimit());
+ Token->getSplit(LineIndex, TailOffset, RemainingSpace);
if (Split.first == StringRef::npos)
break;
assert(Split.first != 0);
- unsigned NewRemainingLength = Token->getLineLengthAfterSplit(
+ unsigned NewRemainingTokenLength = Token->getLineLengthAfterSplit(
LineIndex, TailOffset + Split.first + Split.second);
- if (NewRemainingLength >= RemainingLength)
+ if (NewRemainingTokenLength >= RemainingTokenLength)
break;
if (!DryRun) {
Token->insertBreak(LineIndex, TailOffset, Split, Line.InPPDirective,
Whitespaces);
}
TailOffset += Split.first + Split.second;
- RemainingLength = NewRemainingLength;
+ RemainingTokenLength = NewRemainingTokenLength;
Penalty += Style.PenaltyExcessCharacter;
BreakInserted = true;
}
- State.Column = RemainingLength;
+ PositionAfterLastLineInToken = RemainingTokenLength;
if (!DryRun) {
Token->trimLine(LineIndex, TailOffset, Line.InPPDirective, Whitespaces);
}
}
if (BreakInserted) {
+ State.Column = PositionAfterLastLineInToken + UnbreakableTailLength;
for (unsigned i = 0, e = State.Stack.size(); i != e; ++i)
State.Stack[i].BreakBeforeParameter = true;
State.Stack.back().LastSpace = StartColumn;
@@ -961,6 +1020,10 @@ private:
getRemainingLength(State) + State.Column > getColumnLimit() &&
State.ParenLevel < State.StartOfLineLevel)
return true;
+
+ if (Current.Type == TT_StartOfName && Line.MightBeFunctionDecl &&
+ State.Stack.back().BreakBeforeParameter && State.ParenLevel == 0)
+ return true;
return false;
}
@@ -1082,17 +1145,16 @@ private:
class Formatter : public UnwrappedLineConsumer {
public:
- Formatter(DiagnosticsEngine &Diag, const FormatStyle &Style, Lexer &Lex,
- SourceManager &SourceMgr,
+ Formatter(const FormatStyle &Style, Lexer &Lex, SourceManager &SourceMgr,
const std::vector<CharSourceRange> &Ranges)
- : Diag(Diag), Style(Style), Lex(Lex), SourceMgr(SourceMgr),
+ : Style(Style), Lex(Lex), SourceMgr(SourceMgr),
Whitespaces(SourceMgr, Style), Ranges(Ranges) {}
virtual ~Formatter() {}
tooling::Replacements format() {
LexerBasedFormatTokenSource Tokens(Lex, SourceMgr);
- UnwrappedLineParser Parser(Diag, Style, Tokens, *this);
+ UnwrappedLineParser Parser(Style, Tokens, *this);
bool StructuralError = Parser.parse();
unsigned PreviousEndOfLineColumn = 0;
TokenAnnotator Annotator(Style, SourceMgr, Lex,
@@ -1136,9 +1198,15 @@ public:
(touchesLine(TheLine) || touchesPPDirective(I + 1, E)))
FormatPPDirective = true;
+ // Determine indent and try to merge multiple unwrapped lines.
while (IndentForLevel.size() <= TheLine.Level)
IndentForLevel.push_back(-1);
IndentForLevel.resize(TheLine.Level + 1);
+ unsigned Indent = getIndent(IndentForLevel, TheLine.Level);
+ if (static_cast<int>(Indent) + Offset >= 0)
+ Indent += Offset;
+ tryFitMultipleLinesInOne(Indent, I, E);
+
bool WasMoved = PreviousLineWasTouched && FirstTok.NewlinesBefore == 0;
if (TheLine.First.is(tok::eof)) {
if (PreviousLineWasTouched) {
@@ -1149,9 +1217,6 @@ public:
} else if (TheLine.Type != LT_Invalid &&
(WasMoved || FormatPPDirective || touchesLine(TheLine))) {
unsigned LevelIndent = getIndent(IndentForLevel, TheLine.Level);
- unsigned Indent = LevelIndent;
- if (static_cast<int>(Indent) + Offset >= 0)
- Indent += Offset;
if (FirstTok.WhiteSpaceStart.isValid() &&
// Insert a break even if there is a structural error in case where
// we break apart a line consisting of multiple unwrapped lines.
@@ -1162,7 +1227,6 @@ public:
Indent = LevelIndent =
SourceMgr.getSpellingColumnNumber(FirstTok.Tok.getLocation()) - 1;
}
- tryFitMultipleLinesInOne(Indent, I, E);
UnwrappedLineFormatter Formatter(Style, SourceMgr, TheLine, Indent,
TheLine.First, Whitespaces);
PreviousEndOfLineColumn =
@@ -1171,18 +1235,17 @@ public:
PreviousLineWasTouched = true;
} else {
if (FirstTok.NewlinesBefore > 0 || FirstTok.IsFirst) {
- unsigned Indent =
+ unsigned LevelIndent =
SourceMgr.getSpellingColumnNumber(FirstTok.Tok.getLocation()) - 1;
- unsigned LevelIndent = Indent;
+ // Remove trailing whitespace of the previous line if it was touched.
+ if (PreviousLineWasTouched || touchesEmptyLineBefore(TheLine))
+ formatFirstToken(TheLine.First, PreviousLineLastToken, LevelIndent,
+ TheLine.InPPDirective, PreviousEndOfLineColumn);
+
if (static_cast<int>(LevelIndent) - Offset >= 0)
LevelIndent -= Offset;
if (TheLine.First.isNot(tok::comment))
IndentForLevel[TheLine.Level] = LevelIndent;
-
- // Remove trailing whitespace of the previous line if it was touched.
- if (PreviousLineWasTouched || touchesEmptyLineBefore(TheLine))
- formatFirstToken(TheLine.First, PreviousLineLastToken, Indent,
- TheLine.InPPDirective, PreviousEndOfLineColumn);
}
// If we did not reformat this unwrapped line, the column at the end of
// the last token is unchanged - thus, we can calculate the end of the
@@ -1253,7 +1316,7 @@ private:
return IndentForLevel[Level];
if (Level == 0)
return 0;
- return getIndent(IndentForLevel, Level - 1) + 2;
+ return getIndent(IndentForLevel, Level - 1) + Style.IndentWidth;
}
/// \brief Get the offset of the line relatively to the level.
@@ -1270,8 +1333,6 @@ private:
///
/// This will change \c Line and \c AnnotatedLine to contain the merged line,
/// if possible; note that \c I will be incremented when lines are merged.
- ///
- /// Returns whether the resulting \c Line can fit in a single line.
void tryFitMultipleLinesInOne(unsigned Indent,
std::vector<AnnotatedLine>::iterator &I,
std::vector<AnnotatedLine>::iterator E) {
@@ -1295,7 +1356,6 @@ private:
I->First.FormatTok.IsFirst)) {
tryMergeSimplePPDirective(I, E, Limit);
}
- return;
}
void tryMergeSimplePPDirective(std::vector<AnnotatedLine>::iterator &I,
@@ -1341,13 +1401,17 @@ private:
void tryMergeSimpleBlock(std::vector<AnnotatedLine>::iterator &I,
std::vector<AnnotatedLine>::iterator E,
unsigned Limit) {
+ // No merging if the brace already is on the next line.
+ if (Style.BreakBeforeBraces != FormatStyle::BS_Attach)
+ return;
+
// First, check that the current line allows merging. This is the case if
// we're not in a control flow statement and the last token is an opening
// brace.
AnnotatedLine &Line = *I;
if (Line.First.isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::r_brace,
tok::kw_else, tok::kw_try, tok::kw_catch,
- tok::kw_for,
+ tok::kw_for, tok::kw_namespace,
// This gets rid of all ObjC @ keywords and methods.
tok::at, tok::minus, tok::plus))
return;
@@ -1418,9 +1482,9 @@ private:
bool touchesLine(const AnnotatedLine &TheLine) {
const FormatToken *First = &TheLine.First.FormatTok;
const FormatToken *Last = &TheLine.Last->FormatTok;
- CharSourceRange LineRange = CharSourceRange::getTokenRange(
+ CharSourceRange LineRange = CharSourceRange::getCharRange(
First->WhiteSpaceStart.getLocWithOffset(First->LastNewlineOffset),
- Last->Tok.getLocation());
+ Last->Tok.getLocation().getLocWithOffset(Last->TokenLength - 1));
return touchesRanges(LineRange);
}
@@ -1473,7 +1537,6 @@ private:
}
}
- DiagnosticsEngine &Diag;
FormatStyle Style;
Lexer &Lex;
SourceManager &SourceMgr;
@@ -1484,20 +1547,8 @@ private:
tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
SourceManager &SourceMgr,
- std::vector<CharSourceRange> Ranges,
- DiagnosticConsumer *DiagClient) {
- IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
- OwningPtr<DiagnosticConsumer> DiagPrinter;
- if (DiagClient == 0) {
- DiagPrinter.reset(new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts));
- DiagPrinter->BeginSourceFile(Lex.getLangOpts(), Lex.getPP());
- DiagClient = DiagPrinter.get();
- }
- DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
- DiagClient, false);
- Diagnostics.setSourceManager(&SourceMgr);
- Formatter formatter(Diagnostics, Style, Lex, SourceMgr, Ranges);
+ std::vector<CharSourceRange> Ranges) {
+ Formatter formatter(Style, Lex, SourceMgr, Ranges);
return formatter.format();
}
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 12031166e2..21518c6824 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -101,8 +101,10 @@ private:
return true;
}
if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace,
- tok::pipepipe, tok::ampamp, tok::question,
- tok::colon))
+ tok::question, tok::colon))
+ return false;
+ if (CurrentToken->isOneOf(tok::pipepipe, tok::ampamp) &&
+ Line.First.isNot(tok::kw_template))
return false;
updateParameterCount(Left, CurrentToken);
if (!consumeToken())
@@ -155,6 +157,9 @@ private:
}
if (CurrentToken->is(tok::r_paren)) {
+ if (CurrentToken->Children.empty() ||
+ !CurrentToken->Children[0].isOneOf(tok::l_paren, tok::l_square))
+ Left->DefinesFunctionType = false;
if (CurrentToken->Parent->closesScope())
CurrentToken->Parent->MatchingParen->NoMoreTokensOnLevel = true;
Left->MatchingParen = CurrentToken;
@@ -591,6 +596,7 @@ private:
}
} else if (Current.isOneOf(tok::kw_return, tok::kw_throw) ||
(Current.is(tok::l_paren) && !Line.MustBeDeclaration &&
+ !Line.InPPDirective &&
(!Current.Parent || Current.Parent->isNot(tok::kw_for)))) {
Contexts.back().IsExpression = true;
} else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) {
@@ -871,8 +877,6 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
Line.First.SpacesRequiredBefore = 1;
Line.First.MustBreakBefore = Line.First.FormatTok.MustBreakBefore;
Line.First.CanBreakBefore = Line.First.MustBreakBefore;
-
- Line.First.TotalLength = Line.First.FormatTok.TokenLength;
}
void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
diff --git a/lib/Format/TokenAnnotator.h b/lib/Format/TokenAnnotator.h
index 5ea30159a2..227dd52396 100644
--- a/lib/Format/TokenAnnotator.h
+++ b/lib/Format/TokenAnnotator.h
@@ -75,10 +75,11 @@ public:
: FormatTok(FormatTok), Type(TT_Unknown), SpacesRequiredBefore(0),
CanBreakBefore(false), MustBreakBefore(false),
ClosesTemplateDeclaration(false), MatchingParen(NULL),
- ParameterCount(0), BindingStrength(0), SplitPenalty(0),
- LongestObjCSelectorName(0), DefinesFunctionType(false), Parent(NULL),
- FakeRParens(0), LastInChainOfCalls(false),
- PartOfMultiVariableDeclStmt(false), NoMoreTokensOnLevel(false) {}
+ ParameterCount(0), TotalLength(FormatTok.TokenLength),
+ BindingStrength(0), SplitPenalty(0), LongestObjCSelectorName(0),
+ DefinesFunctionType(false), Parent(NULL), FakeRParens(0),
+ LastInChainOfCalls(false), PartOfMultiVariableDeclStmt(false),
+ NoMoreTokensOnLevel(false) {}
bool is(tok::TokenKind Kind) const { return FormatTok.Tok.is(Kind); }
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index 722af5d2b7..4138bb98ae 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -16,7 +16,6 @@
#define DEBUG_TYPE "format-parser"
#include "UnwrappedLineParser.h"
-#include "clang/Basic/Diagnostic.h"
#include "llvm/Support/Debug.h"
namespace clang {
@@ -125,11 +124,11 @@ private:
UnwrappedLine *PreBlockLine;
};
-UnwrappedLineParser::UnwrappedLineParser(
- clang::DiagnosticsEngine &Diag, const FormatStyle &Style,
- FormatTokenSource &Tokens, UnwrappedLineConsumer &Callback)
+UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
+ FormatTokenSource &Tokens,
+ UnwrappedLineConsumer &Callback)
: Line(new UnwrappedLine), MustBreakBeforeNextToken(false),
- CurrentLines(&Lines), StructuralError(false), Diag(Diag), Style(Style),
+ CurrentLines(&Lines), StructuralError(false), Style(Style),
Tokens(&Tokens), Callback(Callback) {}
bool UnwrappedLineParser::parse() {
@@ -173,9 +172,6 @@ void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
case tok::r_brace:
if (HasOpeningBrace)
return;
- Diag.Report(FormatTok.Tok.getLocation(),
- Diag.getCustomDiagID(clang::DiagnosticsEngine::Error,
- "unexpected '}'"));
StructuralError = true;
nextToken();
addUnwrappedLine();
@@ -402,6 +398,10 @@ void UnwrappedLineParser::parseStructuralElement() {
// structural element.
// FIXME: Figure out cases where this is not true, and add projections for
// them (the one we know is missing are lambdas).
+ if (Style.BreakBeforeBraces == FormatStyle::BS_Linux ||
+ Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup)
+ addUnwrappedLine();
+
parseBlock(/*MustBeDeclaration=*/ false);
addUnwrappedLine();
return;
@@ -577,6 +577,9 @@ void UnwrappedLineParser::parseNamespace() {
if (FormatTok.Tok.is(tok::identifier))
nextToken();
if (FormatTok.Tok.is(tok::l_brace)) {
+ if (Style.BreakBeforeBraces == FormatStyle::BS_Linux)
+ addUnwrappedLine();
+
parseBlock(/*MustBeDeclaration=*/ true, 0);
// Munch the semicolon after a namespace. This is more common than one would
// think. Puttin the semicolon into its own line is very ugly.
@@ -751,8 +754,12 @@ void UnwrappedLineParser::parseRecord() {
}
}
}
- if (FormatTok.Tok.is(tok::l_brace))
+ if (FormatTok.Tok.is(tok::l_brace)) {
+ if (Style.BreakBeforeBraces == FormatStyle::BS_Linux)
+ addUnwrappedLine();
+
parseBlock(/*MustBeDeclaration=*/ true);
+ }
// We fall through to parsing a structural element afterwards, so
// class A {} n, m;
// will end up in one unwrapped line.
diff --git a/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h
index 0c618e24d4..82e93bef48 100644
--- a/lib/Format/UnwrappedLineParser.h
+++ b/lib/Format/UnwrappedLineParser.h
@@ -23,9 +23,6 @@
#include <list>
namespace clang {
-
-class DiagnosticsEngine;
-
namespace format {
/// \brief A wrapper around a \c Token storing information about the
@@ -129,8 +126,7 @@ public:
class UnwrappedLineParser {
public:
- UnwrappedLineParser(clang::DiagnosticsEngine &Diag, const FormatStyle &Style,
- FormatTokenSource &Tokens,
+ UnwrappedLineParser(const FormatStyle &Style, FormatTokenSource &Tokens,
UnwrappedLineConsumer &Callback);
/// Returns true in case of a structural error.
@@ -203,7 +199,6 @@ private:
// indentation levels.
bool StructuralError;
- clang::DiagnosticsEngine &Diag;
const FormatStyle &Style;
FormatTokenSource *Tokens;
UnwrappedLineConsumer &Callback;
diff --git a/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp
index a75c592bfe..7ffebacba5 100644
--- a/lib/Format/WhitespaceManager.cpp
+++ b/lib/Format/WhitespaceManager.cpp
@@ -122,7 +122,7 @@ void WhitespaceManager::addUntouchableComment(unsigned Column) {
std::string WhitespaceManager::getNewLineText(unsigned NewLines,
unsigned Spaces) {
- return std::string(NewLines, '\n') + std::string(Spaces, ' ');
+ return std::string(NewLines, '\n') + getIndentText(Spaces);
}
std::string WhitespaceManager::getNewLineText(unsigned NewLines,
@@ -139,7 +139,15 @@ std::string WhitespaceManager::getNewLineText(unsigned NewLines,
Offset = 0;
}
}
- return NewLineText + std::string(Spaces, ' ');
+ return NewLineText + getIndentText(Spaces);
+}
+
+std::string WhitespaceManager::getIndentText(unsigned Spaces) {
+ if (!Style.UseTab)
+ return std::string(Spaces, ' ');
+
+ return std::string(Spaces / Style.IndentWidth, '\t') +
+ std::string(Spaces % Style.IndentWidth, ' ');
}
void WhitespaceManager::alignComments() {
diff --git a/lib/Format/WhitespaceManager.h b/lib/Format/WhitespaceManager.h
index 5f3dc55eda..1b24b3f6d7 100644
--- a/lib/Format/WhitespaceManager.h
+++ b/lib/Format/WhitespaceManager.h
@@ -78,6 +78,8 @@ private:
unsigned WhitespaceStartColumn,
unsigned EscapedNewlineColumn);
+ std::string getIndentText(unsigned Spaces);
+
/// \brief Structure to store tokens for later layout and alignment.
struct StoredToken {
StoredToken(SourceLocation ReplacementLoc, unsigned ReplacementLength,
diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp
index dcf1f0c70c..478462c3c2 100644
--- a/lib/Lex/HeaderMap.cpp
+++ b/lib/Lex/HeaderMap.cpp
@@ -82,7 +82,7 @@ const HeaderMap *HeaderMap::Create(const FileEntry *FE, FileManager &FM) {
if (FileSize <= sizeof(HMapHeader)) return 0;
OwningPtr<const llvm::MemoryBuffer> FileBuffer(FM.getBufferForFile(FE));
- if (FileBuffer == 0) return 0; // Unreadable file?
+ if (!FileBuffer) return 0; // Unreadable file?
const char *FileStart = FileBuffer->getBufferStart();
// We know the file is at least as big as the header, check it now.
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 50a0cb55f7..ba3291aa39 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -241,7 +241,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
bool FoundElse,
SourceLocation ElseLoc) {
++NumSkipped;
- assert(CurTokenLexer == 0 && CurPPLexer && "Lexing a macro, not a file?");
+ assert(!CurTokenLexer && CurPPLexer && "Lexing a macro, not a file?");
CurPPLexer->pushConditionalLevel(IfTokenLoc, /*isSkipping*/false,
FoundNonSkipPortion, FoundElse);
diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp
index be4defe786..a22d67a6ed 100644
--- a/lib/Lex/PPLexerChange.cpp
+++ b/lib/Lex/PPLexerChange.cpp
@@ -70,7 +70,7 @@ PreprocessorLexer *Preprocessor::getCurrentFileLexer() const {
/// start lexing tokens from it instead of the current buffer.
void Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
SourceLocation Loc) {
- assert(CurTokenLexer == 0 && "Cannot #include a file inside a macro!");
+ assert(!CurTokenLexer && "Cannot #include a file inside a macro!");
++NumEnteredSourceFiles;
if (MaxIncludeStackDepth < IncludeMacroStack.size())
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 6a87b78879..8ad028155a 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2524,7 +2524,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// erroneous: We already checked about that it has no type specifier, and
// C++ doesn't have implicit int. Diagnose it as a typo w.r.t. to the
// typename.
- if (TypeRep == 0) {
+ if (!TypeRep) {
ConsumeToken(); // Eat the scope spec so the identifier is current.
ParsedAttributesWithRange Attrs(AttrFactory);
if (ParseImplicitInt(DS, &SS, TemplateInfo, AS, DSContext, Attrs)) {
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index 507a6b1bcd..e192ae2e23 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -12,8 +12,10 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTConsumer.h"
-#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/Scope.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "RAIIObjectsForParser.h"
using namespace clang;
@@ -21,22 +23,24 @@ using namespace clang;
// OpenMP declarative directives.
//===----------------------------------------------------------------------===//
-/// \brief Parses OpenMP declarative directive
-/// threadprivate-directive
-/// annot_pragma_openmp threadprivate simple-variable-list
+/// \brief Parsing of declarative OpenMP directives.
+///
+/// threadprivate-directive:
+/// annot_pragma_openmp 'threadprivate' simple-variable-list
///
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
SourceLocation Loc = ConsumeToken();
- SmallVector<DeclarationNameInfo, 5> Identifiers;
- OpenMPDirectiveKind Kind = Tok.isAnnotation() ?
- OMPD_unknown :
- getOpenMPDirectiveKind(PP.getSpelling(Tok));
- switch(Kind) {
+ SmallVector<Expr *, 5> Identifiers;
+ OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
+ OMPD_unknown :
+ getOpenMPDirectiveKind(PP.getSpelling(Tok));
+
+ switch (DKind) {
case OMPD_threadprivate:
ConsumeToken();
- if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers)) {
+ if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
// The last seen token is annot_pragma_openmp_end - need to check for
// extra tokens.
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
@@ -44,9 +48,9 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
<< getOpenMPDirectiveName(OMPD_threadprivate);
SkipUntil(tok::annot_pragma_openmp_end, false, true);
}
+ // Skip the last annot_pragma_openmp_end.
ConsumeToken();
return Actions.ActOnOpenMPThreadprivateDirective(Loc,
- getCurScope(),
Identifiers);
}
break;
@@ -55,7 +59,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
break;
default:
Diag(Tok, diag::err_omp_unexpected_directive)
- << getOpenMPDirectiveName(Kind);
+ << getOpenMPDirectiveName(DKind);
break;
}
SkipUntil(tok::annot_pragma_openmp_end, false);
@@ -63,56 +67,69 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
}
/// \brief Parses list of simple variables for '#pragma omp threadprivate'
-/// directive
-/// simple-variable-list:
-/// ( unqualified-id {, unqualified-id} ) annot_pragma_openmp_end
+/// directive.
+///
+/// simple-variable-list:
+/// '(' id-expression {, id-expression} ')'
///
-bool Parser::ParseOpenMPSimpleVarList(
- OpenMPDirectiveKind Kind,
- SmallVectorImpl<DeclarationNameInfo> &IdList) {
+bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
+ SmallVectorImpl<Expr *> &VarList,
+ bool AllowScopeSpecifier) {
+ VarList.clear();
// Parse '('.
- bool IsCorrect = true;
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen_after,
- getOpenMPDirectiveName(Kind))) {
- SkipUntil(tok::annot_pragma_openmp_end, false, true);
- return false;
- }
+ BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+ bool LParen = !T.expectAndConsume(diag::err_expected_lparen_after,
+ getOpenMPDirectiveName(Kind));
+ bool IsCorrect = LParen;
+ bool NoIdentIsFound = true;
// Read tokens while ')' or annot_pragma_openmp_end is not found.
- do {
+ while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
UnqualifiedId Name;
// Read var name.
Token PrevTok = Tok;
+ NoIdentIsFound = false;
- if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
- TemplateKWLoc, Name)) {
+ if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
IsCorrect = false;
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
false, true);
- }
- else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
- Tok.isNot(tok::annot_pragma_openmp_end)) {
+ } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
+ TemplateKWLoc, Name)) {
+ IsCorrect = false;
+ SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+ false, true);
+ } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
+ Tok.isNot(tok::annot_pragma_openmp_end)) {
IsCorrect = false;
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
false, true);
- Diag(PrevTok.getLocation(), diag::err_expected_unqualified_id)
- << getLangOpts().CPlusPlus
+ Diag(PrevTok.getLocation(), diag::err_expected_ident)
<< SourceRange(PrevTok.getLocation(), PrevTokLocation);
} else {
- IdList.push_back(Actions.GetNameFromUnqualifiedId(Name));
+ DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
+ ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS,
+ NameInfo);
+ if (Res.isUsable())
+ VarList.push_back(Res.take());
}
// Consume ','.
if (Tok.is(tok::comma)) {
ConsumeToken();
}
- } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
+ }
- if (IsCorrect || Tok.is(tok::r_paren)) {
- IsCorrect = !T.consumeClose() && IsCorrect;
+ if (NoIdentIsFound) {
+ Diag(Tok, diag::err_expected_ident);
+ IsCorrect = false;
}
- return !IsCorrect && IdList.empty();
+ // Parse ')'.
+ IsCorrect = ((LParen || Tok.is(tok::r_paren)) && !T.consumeClose())
+ && IsCorrect;
+
+ return !IsCorrect && VarList.empty();
}
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 43b6965d31..f47b0e5435 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -2091,8 +2091,8 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
const std::string &TT = TheTriple.getTriple();
const llvm::Target *TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error);
- OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT));
OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
+ OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT));
OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
OwningPtr<llvm::MCSubtargetInfo>
STI(TheTarget->createMCSubtargetInfo(TT, "", ""));
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 2117df45f3..a5371f9e61 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -1897,7 +1897,7 @@ bool BalancedDelimiterTracker::diagnoseOverflow() {
P.Diag(P.Tok, diag::err_bracket_depth_exceeded)
<< P.getLangOpts().BracketDepth;
P.Diag(P.Tok, diag::note_bracket_depth);
- P.SkipUntil(tok::eof);
+ P.SkipUntil(tok::eof, FinalToken);
return true;
}
@@ -1927,7 +1927,8 @@ bool BalancedDelimiterTracker::diagnoseMissingClose() {
}
P.Diag(P.Tok, DID);
P.Diag(LOpen, diag::note_matching) << LHSName;
- if (P.SkipUntil(Close, /*StopAtSemi*/ true, /*DontConsume*/ true))
+ if (P.SkipUntil(Close, FinalToken, /*StopAtSemi*/ true, /*DontConsume*/ true)
+ && P.Tok.is(Close))
LClose = P.ConsumeAnyToken();
return true;
}
diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h
index 213950a6db..f68a2e09fe 100644
--- a/lib/Parse/RAIIObjectsForParser.h
+++ b/lib/Parse/RAIIObjectsForParser.h
@@ -358,7 +358,7 @@ namespace clang {
/// pair, such as braces { ... } or parentheses ( ... ).
class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
Parser& P;
- tok::TokenKind Kind, Close;
+ tok::TokenKind Kind, Close, FinalToken;
SourceLocation (Parser::*Consumer)();
SourceLocation LOpen, LClose;
@@ -377,9 +377,10 @@ namespace clang {
bool diagnoseMissingClose();
public:
- BalancedDelimiterTracker(Parser& p, tok::TokenKind k)
+ BalancedDelimiterTracker(Parser& p, tok::TokenKind k,
+ tok::TokenKind FinalToken = tok::semi)
: GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
- P(p), Kind(k)
+ P(p), Kind(k), FinalToken(FinalToken)
{
switch (Kind) {
default: llvm_unreachable("Unexpected balanced token");
diff --git a/lib/Rewrite/Core/Rewriter.cpp b/lib/Rewrite/Core/Rewriter.cpp
index c1c6595d16..540e8b27fd 100644
--- a/lib/Rewrite/Core/Rewriter.cpp
+++ b/lib/Rewrite/Core/Rewriter.cpp
@@ -463,7 +463,7 @@ public:
}
}
- bool ok() { return FileStream; }
+ bool ok() { return FileStream.isValid(); }
raw_ostream &getStream() { return *FileStream; }
private:
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 3b3ab2c27b..dfce324b70 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -651,7 +651,7 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc,
DeclRep = Rep;
TSTLoc = TagKwLoc;
TSTNameLoc = TagNameLoc;
- TypeSpecOwned = Owned;
+ TypeSpecOwned = Owned && Rep != 0;
return false;
}
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index e718be2f8b..b7810da98e 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -332,7 +332,7 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
if (D->getMostRecentDecl()->isUsed())
return true;
- if (D->hasExternalLinkage())
+ if (D->isExternallyVisible())
return true;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
@@ -402,13 +402,13 @@ void Sema::getUndefinedButUsed(
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
if (FD->isDefined())
continue;
- if (FD->hasExternalLinkage() &&
+ if (FD->isExternallyVisible() &&
!FD->getMostRecentDecl()->isInlined())
continue;
} else {
if (cast<VarDecl>(ND)->hasDefinition() != VarDecl::DeclarationOnly)
continue;
- if (ND->hasExternalLinkage())
+ if (ND->isExternallyVisible())
continue;
}
@@ -435,7 +435,7 @@ static void checkUndefinedButUsed(Sema &S) {
I = Undefined.begin(), E = Undefined.end(); I != E; ++I) {
NamedDecl *ND = I->first;
- if (ND->getLinkage() != ExternalLinkage) {
+ if (!ND->isExternallyVisible()) {
S.Diag(ND->getLocation(), diag::warn_undefined_internal)
<< isa<VarDecl>(ND) << ND;
} else {
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 5d8839a65b..49be515f0b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1194,7 +1194,7 @@ bool Sema::mightHaveNonExternalLinkage(const DeclaratorDecl *D) {
DC = DC->getParent();
}
- return !D->hasExternalLinkage();
+ return !D->isExternallyVisible();
}
bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
@@ -1614,7 +1614,7 @@ static void filterNonConflictingPreviousDecls(ASTContext &context,
if (!old->isHidden())
continue;
- if (old->getLinkage() != ExternalLinkage)
+ if (!old->isExternallyVisible())
filter.erase();
}
@@ -2314,7 +2314,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
// storage classes.
if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) &&
New->getStorageClass() == SC_Static &&
- isExternalLinkage(Old->getLinkage()) &&
+ Old->hasExternalFormalLinkage() &&
!New->getTemplateSpecializationInfo() &&
!canRedefineFunction(Old, getLangOpts())) {
if (getLangOpts().MicrosoftExt) {
@@ -2923,7 +2923,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous,
// [dcl.stc]p8: Check if we have a non-static decl followed by a static.
if (New->getStorageClass() == SC_Static &&
!New->isStaticDataMember() &&
- isExternalLinkage(Old->getLinkage())) {
+ Old->hasExternalFormalLinkage()) {
Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
@@ -4625,13 +4625,13 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) {
static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
// 'weak' only applies to declarations with external linkage.
if (WeakAttr *Attr = ND.getAttr<WeakAttr>()) {
- if (ND.getLinkage() != ExternalLinkage) {
+ if (!ND.isExternallyVisible()) {
S.Diag(Attr->getLocation(), diag::err_attribute_weak_static);
ND.dropAttr<WeakAttr>();
}
}
if (WeakRefAttr *Attr = ND.getAttr<WeakRefAttr>()) {
- if (ND.hasExternalLinkage()) {
+ if (ND.isExternallyVisible()) {
S.Diag(Attr->getLocation(), diag::err_attribute_weakref_not_static);
ND.dropAttr<WeakRefAttr>();
}
@@ -6579,7 +6579,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// If there's a #pragma GCC visibility in scope, and this isn't a class
// member, set the visibility of this function.
- if (!DC->isRecord() && NewFD->hasExternalLinkage())
+ if (!DC->isRecord() && NewFD->isExternallyVisible())
AddPushedVisibilityAttribute(NewFD);
// If there's a #pragma clang arc_cf_code_audited in scope, consider
@@ -7816,7 +7816,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
// declared with no linkage (C99 6.2.2p6), the type for the
// object shall be complete.
if (!Type->isDependentType() && Var->isLocalVarDecl() &&
- !Var->getLinkage() && !Var->isInvalidDecl() &&
+ !Var->hasLinkage() && !Var->isInvalidDecl() &&
RequireCompleteType(Var->getLocation(), Type,
diag::err_typecheck_decl_incomplete_type))
Var->setInvalidDecl();
@@ -8029,7 +8029,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
}
if (var->isThisDeclarationADefinition() &&
- var->hasExternalLinkage() &&
+ var->isExternallyVisible() &&
getDiagnostics().getDiagnosticLevel(
diag::warn_missing_variable_declarations,
var->getLocation())) {
@@ -8138,7 +8138,7 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
const DeclContext *DC = VD->getDeclContext();
// If there's a #pragma GCC visibility in scope, and this isn't a class
// member, set the visibility of this variable.
- if (!DC->isRecord() && VD->hasExternalLinkage())
+ if (!DC->isRecord() && VD->isExternallyVisible())
AddPushedVisibilityAttribute(VD);
if (VD->isFileVarDecl())
@@ -8904,7 +8904,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
// ODR use before the definition. Avoid the expensive map lookup if this
// is the first declaration.
if (FD->getPreviousDecl() != 0 && FD->getPreviousDecl()->isUsed()) {
- if (FD->getLinkage() != ExternalLinkage)
+ if (!FD->isExternallyVisible())
UndefinedButUsed.erase(FD);
else if (FD->isInlined() &&
(LangOpts.CPlusPlus || !LangOpts.GNUInline) &&
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index e5d0316f73..437a9da422 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -9307,7 +9307,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
ParmVarDecl *Other = MoveAssignOperator->getParamDecl(0);
QualType OtherRefType = Other->getType()->
getAs<RValueReferenceType>()->getPointeeType();
- assert(OtherRefType.getQualifiers() == 0 &&
+ assert(!OtherRefType.getQualifiers() &&
"Bad argument type of defaulted move assignment");
// Our location for everything implicitly-generated.
@@ -11824,7 +11824,7 @@ bool Sema::DefineUsedVTables() {
Consumer.HandleVTable(Class, VTablesUsed[Canonical]);
// Optionally warn if we're emitting a weak vtable.
- if (Class->hasExternalLinkage() &&
+ if (Class->isExternallyVisible() &&
Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
const FunctionDecl *KeyFunctionDef = 0;
if (!KeyFunction ||
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index f33e7bcb16..3265ab02dc 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -2945,7 +2945,7 @@ Decl *Sema::ActOnMethodDeclaration(
QualType ArgType;
TypeSourceInfo *DI;
- if (ArgInfo[i].Type == 0) {
+ if (!ArgInfo[i].Type) {
ArgType = Context.getObjCIdType();
DI = 0;
} else {
@@ -3052,6 +3052,8 @@ Decl *Sema::ActOnMethodDeclaration(
Diag(ObjCMethod->getLocation(), diag::err_duplicate_method_decl)
<< ObjCMethod->getDeclName();
Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+ ObjCMethod->setInvalidDecl();
+ return ObjCMethod;
}
// If this Objective-C method does not have a related result type, but we
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index b6b6444738..fa2bfd260b 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -197,11 +197,11 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S,
return;
if (!Current->isInlined())
return;
- if (Current->getLinkage() != ExternalLinkage)
+ if (!Current->isExternallyVisible())
return;
-
+
// Check if the decl has internal linkage.
- if (D->getLinkage() != InternalLinkage)
+ if (D->getFormalLinkage() != InternalLinkage)
return;
// Downgrade from ExtWarn to Extension if
@@ -4468,7 +4468,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
ExprResult
Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
SourceLocation RParenLoc, Expr *InitExpr) {
- assert((Ty != 0) && "ActOnCompoundLiteral(): missing type");
+ assert(Ty && "ActOnCompoundLiteral(): missing type");
// FIXME: put back this assert when initializers are worked out.
//assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
@@ -11459,7 +11459,7 @@ static void MarkVarDeclODRUsed(Sema &SemaRef, VarDecl *Var,
// Keep track of used but undefined variables.
// FIXME: We shouldn't suppress this warning for static data members.
if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly &&
- Var->getLinkage() != ExternalLinkage &&
+ !Var->isExternallyVisible() &&
!(Var->isStaticDataMember() && Var->hasInit())) {
SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()];
if (old.isInvalid()) old = Loc;
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index d37f61ab8a..23116d84ad 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -1221,10 +1221,17 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
else
DiagID = isClassMessage ? diag::warn_class_method_not_found
: diag::warn_inst_method_not_found;
- if (!getLangOpts().DebuggerSupport)
+ if (!getLangOpts().DebuggerSupport) {
Diag(SelLoc, DiagID)
<< Sel << isClassMessage << SourceRange(SelectorLocs.front(),
SelectorLocs.back());
+ // Find the class to which we are sending this message.
+ if (ReceiverType->isObjCObjectPointerType()) {
+ if (ObjCInterfaceDecl *Class =
+ ReceiverType->getAs<ObjCObjectPointerType>()->getInterfaceDecl())
+ Diag(Class->getLocation(), diag::note_receiver_class_declared);
+ }
+ }
// In debuggers, we want to use __unknown_anytype for these
// results so that clients can cast them.
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 7016e565da..a3b78787e4 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -32,54 +32,99 @@ using namespace clang;
// Sema Initialization Checking
//===----------------------------------------------------------------------===//
-static Expr *IsStringInit(Expr *Init, const ArrayType *AT,
- ASTContext &Context) {
+/// \brief Check whether T is compatible with a wide character type (wchar_t,
+/// char16_t or char32_t).
+static bool IsWideCharCompatible(QualType T, ASTContext &Context) {
+ if (Context.typesAreCompatible(Context.getWideCharType(), T))
+ return true;
+ if (Context.getLangOpts().CPlusPlus || Context.getLangOpts().C11) {
+ return Context.typesAreCompatible(Context.Char16Ty, T) ||
+ Context.typesAreCompatible(Context.Char32Ty, T);
+ }
+ return false;
+}
+
+enum StringInitFailureKind {
+ SIF_None,
+ SIF_NarrowStringIntoWideChar,
+ SIF_WideStringIntoChar,
+ SIF_IncompatWideStringIntoWideChar,
+ SIF_Other
+};
+
+/// \brief Check whether the array of type AT can be initialized by the Init
+/// expression by means of string initialization. Returns SIF_None if so,
+/// otherwise returns a StringInitFailureKind that describes why the
+/// initialization would not work.
+static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT,
+ ASTContext &Context) {
if (!isa<ConstantArrayType>(AT) && !isa<IncompleteArrayType>(AT))
- return 0;
+ return SIF_Other;
// See if this is a string literal or @encode.
Init = Init->IgnoreParens();
// Handle @encode, which is a narrow string.
if (isa<ObjCEncodeExpr>(Init) && AT->getElementType()->isCharType())
- return Init;
+ return SIF_None;
// Otherwise we can only handle string literals.
StringLiteral *SL = dyn_cast<StringLiteral>(Init);
- if (SL == 0) return 0;
+ if (SL == 0)
+ return SIF_Other;
- QualType ElemTy = Context.getCanonicalType(AT->getElementType());
+ const QualType ElemTy =
+ Context.getCanonicalType(AT->getElementType()).getUnqualifiedType();
switch (SL->getKind()) {
case StringLiteral::Ascii:
case StringLiteral::UTF8:
// char array can be initialized with a narrow string.
// Only allow char x[] = "foo"; not char x[] = L"foo";
- return ElemTy->isCharType() ? Init : 0;
+ if (ElemTy->isCharType())
+ return SIF_None;
+ if (IsWideCharCompatible(ElemTy, Context))
+ return SIF_NarrowStringIntoWideChar;
+ return SIF_Other;
+ // C99 6.7.8p15 (with correction from DR343), or C11 6.7.9p15:
+ // "An array with element type compatible with a qualified or unqualified
+ // version of wchar_t, char16_t, or char32_t may be initialized by a wide
+ // string literal with the corresponding encoding prefix (L, u, or U,
+ // respectively), optionally enclosed in braces.
case StringLiteral::UTF16:
- return ElemTy->isChar16Type() ? Init : 0;
+ if (Context.typesAreCompatible(Context.Char16Ty, ElemTy))
+ return SIF_None;
+ if (ElemTy->isCharType())
+ return SIF_WideStringIntoChar;
+ if (IsWideCharCompatible(ElemTy, Context))
+ return SIF_IncompatWideStringIntoWideChar;
+ return SIF_Other;
case StringLiteral::UTF32:
- return ElemTy->isChar32Type() ? Init : 0;
+ if (Context.typesAreCompatible(Context.Char32Ty, ElemTy))
+ return SIF_None;
+ if (ElemTy->isCharType())
+ return SIF_WideStringIntoChar;
+ if (IsWideCharCompatible(ElemTy, Context))
+ return SIF_IncompatWideStringIntoWideChar;
+ return SIF_Other;
case StringLiteral::Wide:
- // wchar_t array can be initialized with a wide string: C99 6.7.8p15 (with
- // correction from DR343): "An array with element type compatible with a
- // qualified or unqualified version of wchar_t may be initialized by a wide
- // string literal, optionally enclosed in braces."
- if (Context.typesAreCompatible(Context.getWideCharType(),
- ElemTy.getUnqualifiedType()))
- return Init;
-
- return 0;
+ if (Context.typesAreCompatible(Context.getWideCharType(), ElemTy))
+ return SIF_None;
+ if (ElemTy->isCharType())
+ return SIF_WideStringIntoChar;
+ if (IsWideCharCompatible(ElemTy, Context))
+ return SIF_IncompatWideStringIntoWideChar;
+ return SIF_Other;
}
llvm_unreachable("missed a StringLiteral kind?");
}
-static Expr *IsStringInit(Expr *init, QualType declType, ASTContext &Context) {
+static bool IsStringInit(Expr* init, QualType declType, ASTContext& Context) {
const ArrayType *arrayType = Context.getAsArrayType(declType);
- if (!arrayType) return 0;
-
- return IsStringInit(init, arrayType, Context);
+ if (!arrayType)
+ return false;
+ return IsStringInit(init, arrayType, Context) == SIF_None;
}
/// Update the type of a string literal, including any surrounding parentheses,
@@ -806,10 +851,10 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// array member. There's nothing we can do with the completed
// type here, though.
- if (Expr *Str = IsStringInit(expr, arrayType, SemaRef.Context)) {
+ if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) {
if (!VerifyOnly) {
- CheckStringInit(Str, ElemType, arrayType, SemaRef);
- UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+ CheckStringInit(expr, ElemType, arrayType, SemaRef);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
}
++Index;
return;
@@ -1189,16 +1234,17 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
// Check for the special-case of initializing an array with a string.
if (Index < IList->getNumInits()) {
- if (Expr *Str = IsStringInit(IList->getInit(Index), arrayType,
- SemaRef.Context)) {
+ if (IsStringInit(IList->getInit(Index), arrayType, SemaRef.Context) ==
+ SIF_None) {
// We place the string literal directly into the resulting
// initializer list. This is the only place where the structure
// of the structured initializer list doesn't match exactly,
// because doing so would involve allocating one character
// constant for each string.
if (!VerifyOnly) {
- CheckStringInit(Str, DeclType, arrayType, SemaRef);
- UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+ CheckStringInit(IList->getInit(Index), DeclType, arrayType, SemaRef);
+ UpdateStructuredListElement(StructuredList, StructuredIndex,
+ IList->getInit(Index));
StructuredList->resizeInits(SemaRef.Context, StructuredIndex);
}
++Index;
@@ -2507,6 +2553,10 @@ bool InitializationSequence::isAmbiguous() const {
case FK_TooManyInitsForReference:
case FK_ArrayNeedsInitList:
case FK_ArrayNeedsInitListOrStringLiteral:
+ case FK_ArrayNeedsInitListOrWideStringLiteral:
+ case FK_NarrowStringIntoWideCharArray:
+ case FK_WideStringIntoCharArray:
+ case FK_IncompatWideStringIntoWideChar:
case FK_AddressOfOverloadFailed: // FIXME: Could do better
case FK_NonConstLValueReferenceBindingToTemporary:
case FK_NonConstLValueReferenceBindingToUnrelated:
@@ -4278,9 +4328,23 @@ InitializationSequence::InitializationSequence(Sema &S,
return;
}
- if (Initializer && IsStringInit(Initializer, DestAT, Context)) {
- TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
- return;
+ if (Initializer) {
+ switch (IsStringInit(Initializer, DestAT, Context)) {
+ case SIF_None:
+ TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
+ return;
+ case SIF_NarrowStringIntoWideChar:
+ SetFailed(FK_NarrowStringIntoWideCharArray);
+ return;
+ case SIF_WideStringIntoChar:
+ SetFailed(FK_WideStringIntoCharArray);
+ return;
+ case SIF_IncompatWideStringIntoWideChar:
+ SetFailed(FK_IncompatWideStringIntoWideChar);
+ return;
+ case SIF_Other:
+ break;
+ }
}
// Note: as an GNU C extension, we allow initialization of an
@@ -4307,8 +4371,10 @@ InitializationSequence::InitializationSequence(Sema &S,
TryListInitialization(S, Entity, Kind, cast<InitListExpr>(Initializer),
*this);
AddParenthesizedArrayInitStep(DestType);
- } else if (DestAT->getElementType()->isAnyCharacterType())
+ } else if (DestAT->getElementType()->isCharType())
SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
+ else if (IsWideCharCompatible(DestAT->getElementType(), Context))
+ SetFailed(FK_ArrayNeedsInitListOrWideStringLiteral);
else
SetFailed(FK_ArrayNeedsInitList);
@@ -5816,11 +5882,24 @@ bool InitializationSequence::Diagnose(Sema &S,
break;
case FK_ArrayNeedsInitList:
+ S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 0;
+ break;
case FK_ArrayNeedsInitListOrStringLiteral:
- S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list)
- << (Failure == FK_ArrayNeedsInitListOrStringLiteral);
+ S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 1;
+ break;
+ case FK_ArrayNeedsInitListOrWideStringLiteral:
+ S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 2;
+ break;
+ case FK_NarrowStringIntoWideCharArray:
+ S.Diag(Kind.getLocation(), diag::err_array_init_narrow_string_into_wchar);
+ break;
+ case FK_WideStringIntoCharArray:
+ S.Diag(Kind.getLocation(), diag::err_array_init_wide_string_into_char);
+ break;
+ case FK_IncompatWideStringIntoWideChar:
+ S.Diag(Kind.getLocation(),
+ diag::err_array_init_incompat_wide_string_into_wchar);
break;
-
case FK_ArrayTypeMismatch:
case FK_NonConstantArrayInit:
S.Diag(Kind.getLocation(),
@@ -6192,6 +6271,22 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "array requires initializer list or string literal";
break;
+ case FK_ArrayNeedsInitListOrWideStringLiteral:
+ OS << "array requires initializer list or wide string literal";
+ break;
+
+ case FK_NarrowStringIntoWideCharArray:
+ OS << "narrow string into wide char array";
+ break;
+
+ case FK_WideStringIntoCharArray:
+ OS << "wide string into char array";
+ break;
+
+ case FK_IncompatWideStringIntoWideChar:
+ OS << "incompatible wide string into wide char array";
+ break;
+
case FK_ArrayTypeMismatch:
OS << "array type mismatch";
break;
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 9ab3b2d08e..c70367691f 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -4166,7 +4166,7 @@ std::string TypoCorrection::getAsString(const LangOptions &LO) const {
std::string tmpBuffer;
llvm::raw_string_ostream PrefixOStream(tmpBuffer);
CorrectionNameSpec->print(PrefixOStream, PrintingPolicy(LO));
- CorrectionName.printName(PrefixOStream);
+ PrefixOStream << CorrectionName;
return PrefixOStream.str();
}
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index c815d4f9ab..4953d2d14e 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
/// \file
/// \brief This file implements semantic analysis for OpenMP directives and
-/// clauses
+/// clauses.
///
//===----------------------------------------------------------------------===//
@@ -22,117 +22,121 @@ using namespace clang;
namespace {
- class VarDeclFilterCCC : public CorrectionCandidateCallback {
- private:
- Sema &Actions;
- public:
- VarDeclFilterCCC(Sema &S) : Actions(S) { }
- virtual bool ValidateCandidate(const TypoCorrection &Candidate) {
- NamedDecl *ND = Candidate.getCorrectionDecl();
- if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) {
- return VD->hasGlobalStorage() &&
- Actions.isDeclInScope(ND, Actions.getCurLexicalContext(),
- Actions.getCurScope());
- }
- return false;
- }
- };
+class VarDeclFilterCCC : public CorrectionCandidateCallback {
+private:
+ Sema &Actions;
+public:
+ VarDeclFilterCCC(Sema &S) : Actions(S) { }
+ virtual bool ValidateCandidate(const TypoCorrection &Candidate) {
+ NamedDecl *ND = Candidate.getCorrectionDecl();
+ if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) {
+ return VD->hasGlobalStorage() &&
+ Actions.isDeclInScope(ND, Actions.getCurLexicalContext(),
+ Actions.getCurScope());
+ }
+ return false;
+ }
+};
}
-Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
- SourceLocation Loc,
- Scope *CurScope,
- ArrayRef<DeclarationNameInfo> IdList) {
- SmallVector<DeclRefExpr *, 5> Vars;
- for (ArrayRef<DeclarationNameInfo>::iterator I = IdList.begin(),
- E = IdList.end();
- I != E; ++I) {
- LookupResult Lookup(*this, *I, LookupOrdinaryName);
- LookupParsedName(Lookup, CurScope, NULL, true);
- if (Lookup.isAmbiguous())
- continue;
+ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
+ CXXScopeSpec &ScopeSpec,
+ const DeclarationNameInfo &Id) {
+ LookupResult Lookup(*this, Id, LookupOrdinaryName);
+ LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
- VarDecl *VD;
- if (!Lookup.isSingleResult()) {
- VarDeclFilterCCC Validator(*this);
- TypoCorrection Corrected = CorrectTypo(*I, LookupOrdinaryName, CurScope,
- 0, Validator);
- std::string CorrectedStr = Corrected.getAsString(getLangOpts());
- std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts());
- if (Lookup.empty()) {
- if (Corrected.isResolved()) {
- Diag(I->getLoc(), diag::err_undeclared_var_use_suggest)
- << I->getName() << CorrectedQuotedStr
- << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr);
- } else {
- Diag(I->getLoc(), diag::err_undeclared_var_use)
- << I->getName();
- }
+ if (Lookup.isAmbiguous())
+ return ExprError();
+
+ VarDecl *VD;
+ if (!Lookup.isSingleResult()) {
+ VarDeclFilterCCC Validator(*this);
+ TypoCorrection Corrected = CorrectTypo(Id, LookupOrdinaryName, CurScope,
+ 0, Validator);
+ std::string CorrectedStr = Corrected.getAsString(getLangOpts());
+ std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts());
+ if (Lookup.empty()) {
+ if (Corrected.isResolved()) {
+ Diag(Id.getLoc(), diag::err_undeclared_var_use_suggest)
+ << Id.getName() << CorrectedQuotedStr
+ << FixItHint::CreateReplacement(Id.getLoc(), CorrectedStr);
} else {
- Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest)
- << I->getName() << Corrected.isResolved() << CorrectedQuotedStr
- << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr);
+ Diag(Id.getLoc(), diag::err_undeclared_var_use)
+ << Id.getName();
}
- if (!Corrected.isResolved()) continue;
- VD = Corrected.getCorrectionDeclAs<VarDecl>();
} else {
- if (!(VD = Lookup.getAsSingle<VarDecl>())) {
- Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest)
- << I->getName() << 0;
- Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
- continue;
- }
+ Diag(Id.getLoc(), diag::err_omp_expected_var_arg_suggest)
+ << Id.getName() << Corrected.isResolved() << CorrectedQuotedStr
+ << FixItHint::CreateReplacement(Id.getLoc(), CorrectedStr);
}
-
- // OpenMP [2.9.2, Syntax, C/C++]
- // Variables must be file-scope, namespace-scope, or static block-scope.
- if (!VD->hasGlobalStorage()) {
- Diag(I->getLoc(), diag::err_omp_global_var_arg)
- << getOpenMPDirectiveName(OMPD_threadprivate)
- << !VD->isStaticLocal();
- Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
- continue;
+ if (!Corrected.isResolved()) return ExprError();
+ VD = Corrected.getCorrectionDeclAs<VarDecl>();
+ } else {
+ if (!(VD = Lookup.getAsSingle<VarDecl>())) {
+ Diag(Id.getLoc(), diag::err_omp_expected_var_arg_suggest)
+ << Id.getName() << 0;
+ Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
+ return ExprError();
}
+ }
+ Lookup.suppressDiagnostics();
- // OpenMP [2.9.2, Restrictions, C/C++, p.2]
- // A threadprivate directive for file-scope variables must appear outside
- // any definition or declaration.
- // OpenMP [2.9.2, Restrictions, C/C++, p.3]
- // A threadprivate directive for static class member variables must appear
- // in the class definition, in the same scope in which the member
- // variables are declared.
- // OpenMP [2.9.2, Restrictions, C/C++, p.4]
- // A threadprivate directive for namespace-scope variables must appear
- // outside any definition or declaration other than the namespace
- // definition itself.
- // OpenMP [2.9.2, Restrictions, C/C++, p.6]
- // A threadprivate directive for static block-scope variables must appear
- // in the scope of the variable and not in a nested scope.
- NamedDecl *ND = cast<NamedDecl>(VD);
- if (!isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
- Diag(I->getLoc(), diag::err_omp_var_scope)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
- Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
- continue;
- }
+ // OpenMP [2.9.2, Syntax, C/C++]
+ // Variables must be file-scope, namespace-scope, or static block-scope.
+ if (!VD->hasGlobalStorage()) {
+ Diag(Id.getLoc(), diag::err_omp_global_var_arg)
+ << getOpenMPDirectiveName(OMPD_threadprivate)
+ << !VD->isStaticLocal();
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD;
+ return ExprError();
+ }
- // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
- // A threadprivate directive must lexically precede all references to any
- // of the variables in its list.
- if (VD->isUsed()) {
- Diag(I->getLoc(), diag::err_omp_var_used)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
- continue;
- }
+ // OpenMP [2.9.2, Restrictions, C/C++, p.2]
+ // A threadprivate directive for file-scope variables must appear outside
+ // any definition or declaration.
+ // OpenMP [2.9.2, Restrictions, C/C++, p.3]
+ // A threadprivate directive for static class member variables must appear
+ // in the class definition, in the same scope in which the member
+ // variables are declared.
+ // OpenMP [2.9.2, Restrictions, C/C++, p.4]
+ // A threadprivate directive for namespace-scope variables must appear
+ // outside any definition or declaration other than the namespace
+ // definition itself.
+ // OpenMP [2.9.2, Restrictions, C/C++, p.6]
+ // A threadprivate directive for static block-scope variables must appear
+ // in the scope of the variable and not in a nested scope.
+ NamedDecl *ND = cast<NamedDecl>(VD);
+ if (!isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
+ Diag(Id.getLoc(), diag::err_omp_var_scope)
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
+ return ExprError();
+ }
- QualType ExprType = VD->getType().getNonReferenceType();
- DeclRefExpr *Var = cast<DeclRefExpr>(BuildDeclRefExpr(VD,
- ExprType,
- VK_RValue,
- I->getLoc()).take());
- Vars.push_back(Var);
+ // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
+ // A threadprivate directive must lexically precede all references to any
+ // of the variables in its list.
+ if (VD->isUsed()) {
+ Diag(Id.getLoc(), diag::err_omp_var_used)
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ return ExprError();
}
- if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, Vars)) {
+
+ QualType ExprType = VD->getType().getNonReferenceType();
+ ExprResult DE = BuildDeclRefExpr(VD, ExprType, VK_RValue, Id.getLoc());
+ return DE;
+}
+
+Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
+ SourceLocation Loc,
+ ArrayRef<Expr *> VarList) {
+ if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
CurContext->addDecl(D);
return DeclGroupPtrTy::make(DeclGroupRef(D));
}
@@ -141,18 +145,19 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
SourceLocation Loc,
- ArrayRef<DeclRefExpr *> VarList) {
- SmallVector<DeclRefExpr *, 5> Vars;
- for (ArrayRef<DeclRefExpr *>::iterator I = VarList.begin(),
+ ArrayRef<Expr *> VarList) {
+ SmallVector<Expr *, 8> Vars;
+ for (ArrayRef<Expr *>::iterator I = VarList.begin(),
E = VarList.end();
I != E; ++I) {
- VarDecl *VD = cast<VarDecl>((*I)->getDecl());
- SourceLocation ILoc = (*I)->getLocation();
+ DeclRefExpr *DE = cast<DeclRefExpr>(*I);
+ VarDecl *VD = cast<VarDecl>(DE->getDecl());
+ SourceLocation ILoc = DE->getExprLoc();
// OpenMP [2.9.2, Restrictions, C/C++, p.10]
// A threadprivate variable must not have an incomplete type.
if (RequireCompleteType(ILoc, VD->getType(),
- diag::err_omp_incomplete_type)) {
+ diag::err_omp_threadprivate_incomplete_type)) {
continue;
}
@@ -160,15 +165,21 @@ OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
// A threadprivate variable must not have a reference type.
if (VD->getType()->isReferenceType()) {
Diag(ILoc, diag::err_omp_ref_type_arg)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
- Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
+ << getOpenMPDirectiveName(OMPD_threadprivate);
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
continue;
}
// Check if this is a TLS variable.
if (VD->getTLSKind()) {
Diag(ILoc, diag::err_omp_var_thread_local) << VD;
- Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
continue;
}
@@ -179,3 +190,4 @@ OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
getCurLexicalContext(),
Loc, Vars);
}
+
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index b9695cc1e1..7f1def7daf 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3793,14 +3793,14 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
}
// Address / reference template args must have external linkage in C++98.
- if (Entity->getLinkage() == InternalLinkage) {
+ if (Entity->getFormalLinkage() == InternalLinkage) {
S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_template_arg_object_internal :
diag::ext_template_arg_object_internal)
<< !Func << Entity << Arg->getSourceRange();
S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
<< !Func;
- } else if (Entity->getLinkage() == NoLinkage) {
+ } else if (!Entity->hasLinkage()) {
S.Diag(Arg->getLocStart(), diag::err_template_arg_object_no_linkage)
<< !Func << Entity << Arg->getSourceRange();
S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 42e1757bcb..ff59cdcbc4 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2231,13 +2231,13 @@ Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl(
OMPThreadPrivateDecl *D) {
- SmallVector<DeclRefExpr *, 5> Vars;
- for (ArrayRef<DeclRefExpr *>::iterator I = D->varlist_begin(),
- E = D->varlist_end();
+ SmallVector<Expr *, 5> Vars;
+ for (ArrayRef<Expr *>::iterator I = D->varlist_begin(),
+ E = D->varlist_end();
I != E; ++I) {
Expr *Var = SemaRef.SubstExpr(*I, TemplateArgs).take();
assert(isa<DeclRefExpr>(Var) && "threadprivate arg is not a DeclRefExpr");
- Vars.push_back(cast<DeclRefExpr>(Var));
+ Vars.push_back(Var);
}
OMPThreadPrivateDecl *TD =
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 086acd261d..b117b733a4 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1644,10 +1644,10 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D,
void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
VisitDecl(D);
unsigned NumVars = D->varlist_size();
- SmallVector<DeclRefExpr *, 16> Vars;
+ SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i) {
- Vars.push_back(cast<DeclRefExpr>(Reader.ReadExpr(F)));
+ Vars.push_back(Reader.ReadExpr(F));
}
D->setVars(Vars);
}
@@ -1783,14 +1783,14 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
//prototyped/non-prototyped functions, etc.
if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) {
FunctionDecl *FuncY = cast<FunctionDecl>(Y);
- return (FuncX->getLinkage() == FuncY->getLinkage()) &&
+ return (FuncX->getLinkageInternal() == FuncY->getLinkageInternal()) &&
FuncX->getASTContext().hasSameType(FuncX->getType(), FuncY->getType());
}
// Variables with the same type and linkage match.
if (VarDecl *VarX = dyn_cast<VarDecl>(X)) {
VarDecl *VarY = cast<VarDecl>(Y);
- return (VarX->getLinkage() == VarY->getLinkage()) &&
+ return (VarX->getLinkageInternal() == VarY->getLinkageInternal()) &&
VarX->getASTContext().hasSameType(VarX->getType(), VarY->getType());
}
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 67349db687..7a22afaba7 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -334,7 +334,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
Record.push_back(D->hasImplicitReturnZero());
Record.push_back(D->isConstexpr());
Record.push_back(D->HasSkippedBody);
- Record.push_back(D->getLinkage());
+ Record.push_back(D->getLinkageInternal());
Writer.AddSourceLocation(D->getLocEnd(), Record);
Record.push_back(D->getTemplatedKind());
@@ -694,7 +694,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
Record.push_back(D->isCXXForRangeDecl());
Record.push_back(D->isARCPseudoStrong());
Record.push_back(D->isConstexpr());
- Record.push_back(D->getLinkage());
+ Record.push_back(D->getLinkageInternal());
if (D->getInit()) {
Record.push_back(!D->isInitKnownICE() ? 1 : (D->isInitICE() ? 3 : 2));
diff --git a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index 6388a8df64..ba779ff191 100644
--- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -90,20 +90,49 @@ static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID) {
//===----------------------------------------------------------------------===//
namespace {
- class NilArgChecker : public Checker<check::PreObjCMessage> {
+ class NilArgChecker : public Checker<check::PreObjCMessage,
+ check::PostStmt<ObjCDictionaryLiteral>,
+ check::PostStmt<ObjCArrayLiteral> > {
mutable OwningPtr<APIMisuse> BT;
- void WarnIfNilArg(CheckerContext &C,
- const ObjCMethodCall &msg, unsigned Arg,
- FoundationClass Class,
- bool CanBeSubscript = false) const;
+ void warnIfNilExpr(const Expr *E,
+ const char *Msg,
+ CheckerContext &C) const;
+
+ void warnIfNilArg(CheckerContext &C,
+ const ObjCMethodCall &msg, unsigned Arg,
+ FoundationClass Class,
+ bool CanBeSubscript = false) const;
+
+ void generateBugReport(ExplodedNode *N,
+ StringRef Msg,
+ SourceRange Range,
+ const Expr *Expr,
+ CheckerContext &C) const;
public:
void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
+ void checkPostStmt(const ObjCDictionaryLiteral *DL,
+ CheckerContext &C) const;
+ void checkPostStmt(const ObjCArrayLiteral *AL,
+ CheckerContext &C) const;
};
}
-void NilArgChecker::WarnIfNilArg(CheckerContext &C,
+void NilArgChecker::warnIfNilExpr(const Expr *E,
+ const char *Msg,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ if (State->isNull(C.getSVal(E)).isConstrainedTrue()) {
+
+ if (ExplodedNode *N = C.generateSink()) {
+ generateBugReport(N, Msg, E->getSourceRange(), E, C);
+ }
+
+ }
+}
+
+void NilArgChecker::warnIfNilArg(CheckerContext &C,
const ObjCMethodCall &msg,
unsigned int Arg,
FoundationClass Class,
@@ -113,9 +142,6 @@ void NilArgChecker::WarnIfNilArg(CheckerContext &C,
if (!State->isNull(msg.getArgSVal(Arg)).isConstrainedTrue())
return;
- if (!BT)
- BT.reset(new APIMisuse("nil argument"));
-
if (ExplodedNode *N = C.generateSink()) {
SmallString<128> sbuf;
llvm::raw_svector_ostream os(sbuf);
@@ -149,14 +175,26 @@ void NilArgChecker::WarnIfNilArg(CheckerContext &C,
<< msg.getSelector().getAsString() << "' cannot be nil";
}
}
-
- BugReport *R = new BugReport(*BT, os.str(), N);
- R->addRange(msg.getArgSourceRange(Arg));
- bugreporter::trackNullOrUndefValue(N, msg.getArgExpr(Arg), *R);
- C.emitReport(R);
+
+ generateBugReport(N, os.str(), msg.getArgSourceRange(Arg),
+ msg.getArgExpr(Arg), C);
}
}
+void NilArgChecker::generateBugReport(ExplodedNode *N,
+ StringRef Msg,
+ SourceRange Range,
+ const Expr *E,
+ CheckerContext &C) const {
+ if (!BT)
+ BT.reset(new APIMisuse("nil argument"));
+
+ BugReport *R = new BugReport(*BT, Msg, N);
+ R->addRange(Range);
+ bugreporter::trackNullOrUndefValue(N, E, *R);
+ C.emitReport(R);
+}
+
void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
CheckerContext &C) const {
const ObjCInterfaceDecl *ID = msg.getReceiverInterface();
@@ -225,28 +263,45 @@ void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
if (S.getNameForSlot(0).equals("dictionaryWithObject") &&
S.getNameForSlot(1).equals("forKey")) {
Arg = 0;
- WarnIfNilArg(C, msg, /* Arg */1, Class);
+ warnIfNilArg(C, msg, /* Arg */1, Class);
} else if (S.getNameForSlot(0).equals("setObject") &&
S.getNameForSlot(1).equals("forKey")) {
Arg = 0;
- WarnIfNilArg(C, msg, /* Arg */1, Class);
+ warnIfNilArg(C, msg, /* Arg */1, Class);
} else if (S.getNameForSlot(0).equals("setObject") &&
S.getNameForSlot(1).equals("forKeyedSubscript")) {
CanBeSubscript = true;
Arg = 0;
- WarnIfNilArg(C, msg, /* Arg */1, Class, CanBeSubscript);
+ warnIfNilArg(C, msg, /* Arg */1, Class, CanBeSubscript);
} else if (S.getNameForSlot(0).equals("removeObjectForKey")) {
Arg = 0;
}
}
-
// If argument is '0', report a warning.
if ((Arg != InvalidArgIndex))
- WarnIfNilArg(C, msg, Arg, Class, CanBeSubscript);
+ warnIfNilArg(C, msg, Arg, Class, CanBeSubscript);
}
+void NilArgChecker::checkPostStmt(const ObjCArrayLiteral *AL,
+ CheckerContext &C) const {
+ unsigned NumOfElements = AL->getNumElements();
+ for (unsigned i = 0; i < NumOfElements; ++i) {
+ warnIfNilExpr(AL->getElement(i), "Array element cannot be nil", C);
+ }
+}
+
+void NilArgChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
+ CheckerContext &C) const {
+ unsigned NumOfElements = DL->getNumElements();
+ for (unsigned i = 0; i < NumOfElements; ++i) {
+ ObjCDictionaryElement Element = DL->getKeyValueElement(i);
+ warnIfNilExpr(Element.Key, "Dictionary key cannot be nil", C);
+ warnIfNilExpr(Element.Value, "Dictionary value cannot be nil", C);
+ }
+}
+
//===----------------------------------------------------------------------===//
// Error reporting.
//===----------------------------------------------------------------------===//
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 00c92d8153..fe579a3fbf 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -1465,9 +1465,7 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
SmallString<256> Buf;
llvm::raw_svector_ostream Out(Buf);
- Out << "Assuming '";
- VD->getDeclName().printName(Out);
- Out << "' is ";
+ Out << "Assuming '" << VD->getDeclName() << "' is ";
QualType VDTy = VD->getType();
diff --git a/lib/StaticAnalyzer/Core/CheckerContext.cpp b/lib/StaticAnalyzer/Core/CheckerContext.cpp
index 74eeef1c67..6b22bf411c 100644
--- a/lib/StaticAnalyzer/Core/CheckerContext.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerContext.cpp
@@ -68,7 +68,7 @@ bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD,
// If this function is not externally visible, it is not a C library function.
// Note that we make an exception for inline functions, which may be
// declared in header files without external linkage.
- if (!FD->isInlined() && FD->getLinkage() != ExternalLinkage)
+ if (!FD->isInlined() && !FD->isExternallyVisible())
return false;
if (Name.empty())
diff --git a/test/Analysis/NSContainers.m b/test/Analysis/NSContainers.m
index 6b4089b3e5..959f367d28 100644
--- a/test/Analysis/NSContainers.m
+++ b/test/Analysis/NSContainers.m
@@ -36,6 +36,10 @@ typedef struct _NSZone NSZone;
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx __attribute__((availability(macosx,introduced=10.8)));
@end
+@interface NSArray (NSArrayCreation)
++ (instancetype)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
+@end
+
@interface NSMutableArray : NSArray
- (void)addObject:(id)anObject;
@@ -58,6 +62,8 @@ typedef struct _NSZone NSZone;
+ (id)dictionary;
+ (id)dictionaryWithObject:(id)object forKey:(id <NSCopying>)key;
++ (instancetype)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt;
+
@end
@interface NSMutableDictionary : NSDictionary
@@ -147,6 +153,33 @@ NSDictionary *testNilArgNSDictionary2(NSObject *obj) {
return [NSDictionary dictionaryWithObject:obj forKey:0]; // expected-warning {{Key argument to 'dictionaryWithObject:forKey:' cannot be nil}}
}
+id testCreateDictionaryLiteralKey(id value, id nilKey) {
+ if (nilKey)
+ ;
+ return @{@"abc":value, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}}
+}
+
+id testCreateDictionaryLiteralValue(id nilValue) {
+ if (nilValue)
+ ;
+ return @{@"abc":nilValue}; // expected-warning {{Dictionary value cannot be nil}}
+}
+
+id testCreateDictionaryLiteral(id nilValue, id nilKey) {
+ if (nilValue)
+ ;
+ if (nilKey)
+ ;
+ return @{@"abc":nilValue, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}}
+ // expected-warning@-1 {{Dictionary value cannot be nil}}
+}
+
+id testCreateArrayLiteral(id myNil) {
+ if (myNil)
+ ;
+ return @[ @"a", myNil, @"c" ]; // expected-warning {{Array element cannot be nil}}
+}
+
// Test inline defensive checks suppression.
void idc(id x) {
if (x)
diff --git a/test/Analysis/inlining/DynDispatchBifurcate.m b/test/Analysis/inlining/DynDispatchBifurcate.m
index ab1dfc5ec1..0ce079654e 100644
--- a/test/Analysis/inlining/DynDispatchBifurcate.m
+++ b/test/Analysis/inlining/DynDispatchBifurcate.m
@@ -181,11 +181,11 @@ int testPropertySynthesized(PublicClass *p) {
}
// Test definition not available edge case.
-@interface DefNotAvailClass : NSObject
+@interface DefNotAvailClass : NSObject // expected-note {{receiver is instance of class declared here}}
@end
id testDefNotAvailableInlined(DefNotAvailClass *C) {
return [C mem]; // expected-warning {{instance method '-mem' not found}}
}
id testDefNotAvailable(DefNotAvailClass *C) {
return testDefNotAvailableInlined(C);
-} \ No newline at end of file
+}
diff --git a/test/Analysis/inlining/path-notes.m b/test/Analysis/inlining/path-notes.m
index 74f088a382..602bad188a 100644
--- a/test/Analysis/inlining/path-notes.m
+++ b/test/Analysis/inlining/path-notes.m
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=text -analyzer-config suppress-null-return-paths=false -fblocks -verify %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config suppress-null-return-paths=false -fblocks %s -o %t.plist
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NilArg -analyzer-output=text -analyzer-config suppress-null-return-paths=false -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NilArg -analyzer-output=plist-multi-file -analyzer-config suppress-null-return-paths=false -fblocks %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
typedef struct dispatch_queue_s *dispatch_queue_t;
@@ -11,6 +11,57 @@ void dispatch_sync(dispatch_queue_t, dispatch_block_t);
@property int *p;
@end
+typedef unsigned long NSUInteger;
+typedef signed char BOOL;
+typedef struct _NSZone NSZone;
+@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
+@protocol NSObject
+@end
+@protocol NSCopying
+- (id)copyWithZone:(NSZone *)zone;
+@end
+@protocol NSMutableCopying
+- (id)mutableCopyWithZone:(NSZone *)zone;
+@end
+@protocol NSCoding
+- (void)encodeWithCoder:(NSCoder *)aCoder;
+@end
+@protocol NSFastEnumeration
+@end
+@protocol NSSecureCoding <NSCoding>
+@required
++ (BOOL)supportsSecureCoding;
+@end
+@interface NSObject <NSObject> {}
+- (id)init;
++ (id)alloc;
+@end
+@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
+
+- (NSUInteger)count;
+- (id)objectAtIndex:(NSUInteger)index;
+
+@end
+
+@interface NSArray (NSExtendedArray)
+- (NSArray *)arrayByAddingObject:(id)anObject;
+- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx __attribute__((availability(macosx,introduced=10.8)));
+@end
+
+@interface NSArray (NSArrayCreation)
++ (instancetype)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
+@end
+
+@interface NSMutableArray : NSArray
+
+- (void)addObject:(id)anObject;
+- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
+- (void)removeLastObject;
+- (void)removeObjectAtIndex:(NSUInteger)index;
+- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
+
+@end
+
int *getZeroIfNil(Test *x) {
return x.p;
// expected-note@-1 {{'p' not called because the receiver is nil}}
@@ -89,6 +140,12 @@ void testNilReceiver(id *x) {
// expected-note@-3 {{Calling 'testNilReceiverHelper'}}
}
+id testCreateArrayLiteral(id myNil) {
+ if (myNil) // expected-note {{Assuming 'myNil' is nil}}
+ ; // expected-note@-1 {{Taking false branch}}
+ return @[ @"a", myNil, @"c" ]; // expected-warning {{Array element cannot be nil}}
+ //expected-note@-1 {{Array element cannot be nil}}
+}
// CHECK: <key>diagnostics</key>
// CHECK-NEXT: <array>
@@ -103,12 +160,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -116,12 +173,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>17</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>17</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -133,7 +190,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>17</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -141,12 +198,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>17</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>17</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -166,12 +223,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>17</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>17</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -179,12 +236,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>15</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -196,7 +253,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -204,12 +261,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>18</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -225,7 +282,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
+// CHECK-NEXT: <key>line</key><integer>65</integer>
// CHECK-NEXT: <key>col</key><integer>1</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -243,12 +300,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
+// CHECK-NEXT: <key>line</key><integer>65</integer>
// CHECK-NEXT: <key>col</key><integer>1</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
+// CHECK-NEXT: <key>line</key><integer>65</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -256,12 +313,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -277,12 +334,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -290,12 +347,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -307,7 +364,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -315,12 +372,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -340,12 +397,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -353,12 +410,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -370,7 +427,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -378,12 +435,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>66</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -399,7 +456,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -407,12 +464,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>18</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -432,12 +489,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>15</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -445,12 +502,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>20</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>20</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -462,7 +519,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>20</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -470,12 +527,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>22</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -496,7 +553,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>issue_hash</key><string>1</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
// CHECK-NEXT: <key>col</key><integer>20</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -512,12 +569,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
+// CHECK-NEXT: <key>line</key><integer>81</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
+// CHECK-NEXT: <key>line</key><integer>81</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -525,12 +582,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
// CHECK-NEXT: <key>col</key><integer>15</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -542,7 +599,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -550,12 +607,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
+// CHECK-NEXT: <key>line</key><integer>92</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -599,7 +656,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
// CHECK-NEXT: <key>col</key><integer>30</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -617,12 +674,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
// CHECK-NEXT: <key>col</key><integer>30</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
// CHECK-NEXT: <key>col</key><integer>30</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -630,12 +687,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
+// CHECK-NEXT: <key>line</key><integer>89</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
+// CHECK-NEXT: <key>line</key><integer>89</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -647,7 +704,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
+// CHECK-NEXT: <key>line</key><integer>89</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -655,12 +712,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
+// CHECK-NEXT: <key>line</key><integer>89</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
+// CHECK-NEXT: <key>line</key><integer>89</integer>
// CHECK-NEXT: <key>col</key><integer>9</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -690,7 +747,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -698,12 +755,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
+// CHECK-NEXT: <key>line</key><integer>92</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -723,12 +780,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
// CHECK-NEXT: <key>col</key><integer>15</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -736,12 +793,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
+// CHECK-NEXT: <key>line</key><integer>94</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
+// CHECK-NEXT: <key>line</key><integer>94</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -753,7 +810,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
+// CHECK-NEXT: <key>line</key><integer>94</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -761,12 +818,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
+// CHECK-NEXT: <key>line</key><integer>94</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
+// CHECK-NEXT: <key>line</key><integer>94</integer>
// CHECK-NEXT: <key>col</key><integer>14</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -787,7 +844,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>issue_hash</key><string>14</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
+// CHECK-NEXT: <key>line</key><integer>94</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -803,12 +860,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
+// CHECK-NEXT: <key>line</key><integer>102</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
+// CHECK-NEXT: <key>line</key><integer>102</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -816,12 +873,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
+// CHECK-NEXT: <key>line</key><integer>107</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
+// CHECK-NEXT: <key>line</key><integer>107</integer>
// CHECK-NEXT: <key>col</key><integer>15</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -833,7 +890,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
+// CHECK-NEXT: <key>line</key><integer>107</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -841,12 +898,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
+// CHECK-NEXT: <key>line</key><integer>107</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
+// CHECK-NEXT: <key>line</key><integer>113</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -890,7 +947,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
+// CHECK-NEXT: <key>line</key><integer>107</integer>
// CHECK-NEXT: <key>col</key><integer>30</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -908,12 +965,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
+// CHECK-NEXT: <key>line</key><integer>107</integer>
// CHECK-NEXT: <key>col</key><integer>30</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
+// CHECK-NEXT: <key>line</key><integer>107</integer>
// CHECK-NEXT: <key>col</key><integer>30</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -921,12 +978,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
+// CHECK-NEXT: <key>line</key><integer>109</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
+// CHECK-NEXT: <key>line</key><integer>109</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -938,7 +995,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
+// CHECK-NEXT: <key>line</key><integer>109</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -946,12 +1003,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
+// CHECK-NEXT: <key>line</key><integer>109</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
+// CHECK-NEXT: <key>line</key><integer>109</integer>
// CHECK-NEXT: <key>col</key><integer>9</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -971,12 +1028,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
+// CHECK-NEXT: <key>line</key><integer>109</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
+// CHECK-NEXT: <key>line</key><integer>109</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -984,12 +1041,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
+// CHECK-NEXT: <key>line</key><integer>111</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
+// CHECK-NEXT: <key>line</key><integer>111</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1001,7 +1058,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
+// CHECK-NEXT: <key>line</key><integer>111</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1009,12 +1066,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
+// CHECK-NEXT: <key>line</key><integer>111</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
+// CHECK-NEXT: <key>line</key><integer>111</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1032,7 +1089,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>type</key><string>uninitialized variable captured by block</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
+// CHECK-NEXT: <key>line</key><integer>111</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1048,12 +1105,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
+// CHECK-NEXT: <key>line</key><integer>133</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
+// CHECK-NEXT: <key>line</key><integer>133</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1061,12 +1118,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>23</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1082,12 +1139,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>23</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1095,12 +1152,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1112,7 +1169,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1120,12 +1177,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>27</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1145,12 +1202,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1158,12 +1215,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>25</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>25</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1175,7 +1232,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>25</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1183,12 +1240,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>25</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>35</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1204,7 +1261,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1212,12 +1269,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>line</key><integer>137</integer>
// CHECK-NEXT: <key>col</key><integer>36</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1233,7 +1290,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
+// CHECK-NEXT: <key>line</key><integer>127</integer>
// CHECK-NEXT: <key>col</key><integer>1</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1251,12 +1308,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
+// CHECK-NEXT: <key>line</key><integer>127</integer>
// CHECK-NEXT: <key>col</key><integer>1</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
+// CHECK-NEXT: <key>line</key><integer>127</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1264,12 +1321,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>line</key><integer>128</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>line</key><integer>128</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1285,12 +1342,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>line</key><integer>128</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>line</key><integer>128</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1298,12 +1355,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>line</key><integer>128</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>line</key><integer>128</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1315,7 +1372,7 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>line</key><integer>128</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1323,12 +1380,12 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>line</key><integer>128</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>line</key><integer>128</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1349,9 +1406,186 @@ void testNilReceiver(id *x) {
// CHECK-NEXT: <key>issue_hash</key><string>1</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>line</key><integer>128</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>path</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming &apos;myNil&apos; is nil</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming &apos;myNil&apos; is nil</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>146</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>146</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>146</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>146</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>146</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>146</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>146</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>146</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>146</integer>
+// CHECK-NEXT: <key>col</key><integer>23</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Array element cannot be nil</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Array element cannot be nil</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Array element cannot be nil</string>
+// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
+// CHECK-NEXT: <key>type</key><string>nil argument</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>testCreateArrayLiteral</string>
+// CHECK-NEXT: <key>issue_hash</key><string>3</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>146</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
diff --git a/test/Analysis/rdar-6540084.m b/test/Analysis/rdar-6540084.m
index 7070709e57..e928710b38 100644
--- a/test/Analysis/rdar-6540084.m
+++ b/test/Analysis/rdar-6540084.m
@@ -9,13 +9,13 @@ typedef struct _NSZone NSZone;
@protocol NSObject - (BOOL)isEqual:(id)object; @end
@interface NSObject <NSObject> {} @end
extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
-@class NSArray;
+@class NSArray; // expected-note {{receiver is instance of class declared here}}
@class NSMutableArray, NSIndexSet, NSView, NSPredicate, NSString, NSViewAnimation, NSTimer; // expected-note{{forward declaration of class here}}
@interface FooBazController : NSObject {}
@end
typedef struct {} TazVersion;
@class TazNode;
-@interface TazGuttenberg : NSObject {} typedef NSUInteger BugsBunnyType; @end
+@interface TazGuttenberg : NSObject {} typedef NSUInteger BugsBunnyType; @end // expected-note {{receiver is instance of class declared here}}
@interface FooBaz : NSObject {}
@property (nonatomic) BugsBunnyType matchType;
@property (nonatomic, retain) NSArray *papyrus; @end
diff --git a/test/CodeGen/arm-clear.c b/test/CodeGen/arm-clear.c
index 51506dfed1..8ef3675641 100644
--- a/test/CodeGen/arm-clear.c
+++ b/test/CodeGen/arm-clear.c
@@ -1,21 +1,8 @@
// REQUIRES: arm-registered-target
// RUN: %clang_cc1 -triple armv7-apple-darwin9 -emit-llvm -w -o - %s | FileCheck %s
-void clear0(void *ptr) {
- // CHECK: clear0
- // CHECK-NOT: load i8**
- __clear_cache();
-}
-
-void clear1(void *ptr) {
- // CHECK: clear1
- // CHECK: load i8**
- // CHECK-NOT: load i8**
- __clear_cache(ptr);
-}
-
-void clear2(void *ptr, void *ptr2) {
- // CHECK: clear2
+void clear(void *ptr, void *ptr2) {
+ // CHECK: clear
// CHECK: load i8**
// CHECK: load i8**
__clear_cache(ptr, ptr2);
diff --git a/test/CodeGen/arm-neon-vget.c b/test/CodeGen/arm-neon-vget.c
new file mode 100644
index 0000000000..4a710a2ad8
--- /dev/null
+++ b/test/CodeGen/arm-neon-vget.c
@@ -0,0 +1,124 @@
+// REQUIRES: arm-registered-target
+// RUN: %clang_cc1 -triple thumbv7-apple-darwin \
+// RUN: -target-abi apcs-gnu \
+// RUN: -target-cpu cortex-a8 \
+// RUN: -mfloat-abi soft \
+// RUN: -target-feature +soft-float-abi \
+// RUN: -ffreestanding \
+// RUN: -emit-llvm -w -O1 -o - %s | FileCheck %s
+
+#include <arm_neon.h>
+
+// Check that the vget_low/vget_high intrinsics generate a single shuffle
+// without any bitcasting.
+int8x8_t low_s8(int8x16_t a) {
+// CHECK: shufflevector <16 x i8> %a, <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ return vget_low_s8(a);
+}
+
+uint8x8_t low_u8 (uint8x16_t a) {
+// CHECK: shufflevector <16 x i8> %a, <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ return vget_low_u8(a);
+}
+
+int16x4_t low_s16( int16x8_t a) {
+// CHECK: shufflevector <8 x i16> %a, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ return vget_low_s16(a);
+}
+
+uint16x4_t low_u16(uint16x8_t a) {
+// CHECK: shufflevector <8 x i16> %a, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ return vget_low_u16(a);
+}
+
+int32x2_t low_s32( int32x4_t a) {
+// CHECK: shufflevector <4 x i32> %a, <4 x i32> undef, <2 x i32> <i32 0, i32 1>
+ return vget_low_s32(a);
+}
+
+uint32x2_t low_u32(uint32x4_t a) {
+// CHECK: shufflevector <4 x i32> %a, <4 x i32> undef, <2 x i32> <i32 0, i32 1>
+ return vget_low_u32(a);
+}
+
+int64x1_t low_s64( int64x2_t a) {
+// CHECK: shufflevector <2 x i64> %a, <2 x i64> undef, <1 x i32> zeroinitializer
+ return vget_low_s64(a);
+}
+
+uint64x1_t low_u64(uint64x2_t a) {
+// CHECK: shufflevector <2 x i64> %a, <2 x i64> undef, <1 x i32> zeroinitializer
+ return vget_low_u64(a);
+}
+
+poly8x8_t low_p8 (poly8x16_t a) {
+// CHECK: shufflevector <16 x i8> %a, <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ return vget_low_p8(a);
+}
+
+poly16x4_t low_p16(poly16x8_t a) {
+// CHECK: shufflevector <8 x i16> %a, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ return vget_low_p16(a);
+}
+
+float32x2_t low_f32(float32x4_t a) {
+// CHECK: shufflevector <4 x float> %a, <4 x float> undef, <2 x i32> <i32 0, i32 1>
+ return vget_low_f32(a);
+}
+
+
+int8x8_t high_s8(int8x16_t a) {
+// CHECK: shufflevector <16 x i8> %a, <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ return vget_high_s8(a);
+}
+
+uint8x8_t high_u8 (uint8x16_t a) {
+// CHECK: shufflevector <16 x i8> %a, <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ return vget_high_u8(a);
+}
+
+int16x4_t high_s16( int16x8_t a) {
+// CHECK: shufflevector <8 x i16> %a, <8 x i16> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ return vget_high_s16(a);
+}
+
+uint16x4_t high_u16(uint16x8_t a) {
+// CHECK: shufflevector <8 x i16> %a, <8 x i16> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ return vget_high_u16(a);
+}
+
+int32x2_t high_s32( int32x4_t a) {
+// CHECK: shufflevector <4 x i32> %a, <4 x i32> undef, <2 x i32> <i32 2, i32 3>
+ return vget_high_s32(a);
+}
+
+uint32x2_t high_u32(uint32x4_t a) {
+// CHECK: shufflevector <4 x i32> %a, <4 x i32> undef, <2 x i32> <i32 2, i32 3>
+ return vget_high_u32(a);
+}
+
+int64x1_t high_s64( int64x2_t a) {
+// CHECK: shufflevector <2 x i64> %a, <2 x i64> undef, <1 x i32> <i32 1>
+ return vget_high_s64(a);
+}
+
+uint64x1_t high_u64(uint64x2_t a) {
+// CHECK: shufflevector <2 x i64> %a, <2 x i64> undef, <1 x i32> <i32 1>
+ return vget_high_u64(a);
+}
+
+poly8x8_t high_p8 (poly8x16_t a) {
+// CHECK: shufflevector <16 x i8> %a, <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ return vget_high_p8(a);
+}
+
+poly16x4_t high_p16(poly16x8_t a) {
+// CHECK: shufflevector <8 x i16> %a, <8 x i16> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ return vget_high_p16(a);
+}
+
+float32x2_t high_f32(float32x4_t a) {
+// CHECK: shufflevector <4 x float> %a, <4 x float> undef, <2 x i32> <i32 2, i32 3>
+ return vget_high_f32(a);
+}
+
diff --git a/test/CodeGen/linux-arm-atomic.c b/test/CodeGen/linux-arm-atomic.c
new file mode 100644
index 0000000000..c7ce1d228b
--- /dev/null
+++ b/test/CodeGen/linux-arm-atomic.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv7-unknown-linux | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv6-unknown-linux | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-unknown-linux | FileCheck %s
+
+typedef int _Atomic_word;
+_Atomic_word exchange_and_add(volatile _Atomic_word *__mem, int __val) {
+ return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL);
+}
+
+// CHECK: define {{.*}} @exchange_and_add
+// CHECK: atomicrmw {{.*}} add
diff --git a/test/CodeGenCXX/captured-statements.cpp b/test/CodeGenCXX/captured-statements.cpp
index 91c7ff28f0..cfa6936111 100644
--- a/test/CodeGenCXX/captured-statements.cpp
+++ b/test/CodeGenCXX/captured-statements.cpp
@@ -55,9 +55,9 @@ void test2(int x) {
}();
// CHECK-2: define void @_Z5test2i
- // CHECK-2: call i32 @[[Lambda:["$\w]+]]
+ // CHECK-2: call {{.*}} @[[Lambda:["$\w]+]]
//
- // CHECK-2: define internal i32 @[[Lambda]]
+ // CHECK-2: define internal {{.*}} @[[Lambda]]
// CHECK-2: call void @[[HelperName:["$_A-Za-z0-9]+]](%[[Capture:.*]]*
//
// CHECK-2: define internal void @[[HelperName]]
@@ -74,7 +74,7 @@ void test3(int x) {
// CHECK-3: %[[Capture:struct\.anon[\.0-9]*]] = type { i32* }
- // CHECK-3: define void @_Z5test3i(i32 %x)
+ // CHECK-3: define void @_Z5test3i
// CHECK-3: store i32*
// CHECK-3: call void @{{.*}}__captured_stmt
// CHECK-3: ret void
@@ -86,10 +86,7 @@ void test4() {
Foo f;
f.x = 5;
}
- // CHECK-4: %[[Capture:struct\.anon[\.0-9]*]] = type { i32* }
-
- // CHECK-4: define void @_Z5test3i(i32 %x)
- // CHECK-4: store i32*
+ // CHECK-4: define void @_Z5test4v
// CHECK-4: call void @[[HelperName:["$_A-Za-z0-9]+]](%[[Capture:.*]]*
// CHECK-4: ret void
//
diff --git a/test/CodeGenCXX/cxx1y-deduced-return-type.cpp b/test/CodeGenCXX/cxx1y-deduced-return-type.cpp
new file mode 100644
index 0000000000..6d15a2246d
--- /dev/null
+++ b/test/CodeGenCXX/cxx1y-deduced-return-type.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -std=c++1y -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: @x = global {{.*}} zeroinitializer
+
+// CHECK: define {{.*}} @_Z1fv
+inline auto f() {
+ int n = 0;
+ // CHECK: load i32
+ // CHECK: store i32
+ // CHECK: ret
+ return [=] () mutable { return ++n; };
+}
+
+auto x = f();
+
+template<typename T> auto *g(T t) { return t; }
+template<typename T> decltype(auto) h(T t) { return t; }
+
+// CHECK: define {{.*}} @_Z1zv
+void z() {
+ // CHECK: call {{.*}} @_Z1gIPZ1fvEUlvE_EPDaT_(
+ // CHECK: call {{.*}} @_Z1hIPZ1fvEUlvE_EDcT_(
+ g(&x);
+ h(&x);
+}
+
+auto i() { return [] {}; }
+// CHECK: define {{.*}} @_Z1jv
+auto j() {
+ // CHECK: call {{.*}} @"_Z1hIZ1ivE3$_0EDcT_"()
+ h(i());
+}
diff --git a/test/CodeGenCXX/debug-info-namespace.cpp b/test/CodeGenCXX/debug-info-namespace.cpp
index 4b44661eb1..9eff818f87 100644
--- a/test/CodeGenCXX/debug-info-namespace.cpp
+++ b/test/CodeGenCXX/debug-info-namespace.cpp
@@ -8,6 +8,7 @@ void f1() { }
void f1(int) { }
struct foo;
struct bar { };
+typedef bar baz;
}
using namespace B;
}
@@ -24,6 +25,7 @@ int func(bool b) {
using B::bar;
using B::f1;
using B::i;
+ using B::baz;
bar x;
return i;
}
@@ -33,24 +35,27 @@ int func(bool b) {
// CHECK: [[CU:![0-9]*]] = {{.*}}[[MODULES:![0-9]*]], metadata !""} ; [ DW_TAG_compile_unit ]
// CHECK: [[FILE:![0-9]*]] {{.*}}debug-info-namespace.cpp"
+// CHECK: [[FOOCPP:![0-9]*]] = metadata !{metadata !"foo.cpp", {{.*}}
// CHECK: [[NS:![0-9]*]] = {{.*}}, metadata [[FILE2:![0-9]*]], metadata [[CTXT:![0-9]*]], {{.*}} ; [ DW_TAG_namespace ] [B] [line 1]
// CHECK: [[CTXT]] = {{.*}}, metadata [[FILE]], null, {{.*}} ; [ DW_TAG_namespace ] [A] [line 3]
// CHECK: [[F1:![0-9]*]] {{.*}} ; [ DW_TAG_subprogram ] [line 4] [def] [f1]
-// CHECK: [[FUNC:![0-9]*]] {{.*}} ; [ DW_TAG_subprogram ] [line 13] [def] [func]
+// CHECK: [[FUNC:![0-9]*]] {{.*}} ; [ DW_TAG_subprogram ] [line 14] [def] [func]
// CHECK: [[FILE2]]} ; [ DW_TAG_file_type ] [{{.*}}foo.cpp]
// CHECK: [[I:![0-9]*]] = {{.*}}, metadata [[NS]], metadata !"i", {{.*}} ; [ DW_TAG_variable ] [i]
-// CHECK: [[MODULES]] = metadata !{metadata [[M1:![0-9]*]], metadata [[M2:![0-9]*]], metadata [[M3:![0-9]*]], metadata [[M4:![0-9]*]], metadata [[M5:![0-9]*]], metadata [[M6:![0-9]*]], metadata [[M7:![0-9]*]], metadata [[M8:![0-9]*]]}
-// CHECK: [[M1]] = metadata !{i32 {{[0-9]*}}, metadata [[CTXT]], metadata [[NS]], i32 8} ; [ DW_TAG_imported_module ]
-// CHECK: [[M2]] = metadata !{i32 {{[0-9]*}}, metadata [[CU]], metadata [[CTXT]], i32 11} ; [ DW_TAG_imported_module ]
-// CHECK: [[M3]] = metadata !{i32 {{[0-9]*}}, metadata [[LEX:![0-9]*]], metadata [[NS]], i32 15} ; [ DW_TAG_imported_module ]
-// CHECK: [[LEX]] = metadata !{i32 {{[0-9]*}}, metadata [[FILE2]], metadata [[FUNC]], i32 14, i32 0, i32 0} ; [ DW_TAG_lexical_block ]
-// CHECK: [[M4]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[CTXT]], i32 18} ; [ DW_TAG_imported_module ]
-// CHECK: [[M5]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[FOO:![0-9]*]], i32 19} ; [ DW_TAG_imported_declaration ]
+// CHECK: [[MODULES]] = metadata !{metadata [[M1:![0-9]*]], metadata [[M2:![0-9]*]], metadata [[M3:![0-9]*]], metadata [[M4:![0-9]*]], metadata [[M5:![0-9]*]], metadata [[M6:![0-9]*]], metadata [[M7:![0-9]*]], metadata [[M8:![0-9]*]], metadata [[M9:![0-9]*]]}
+// CHECK: [[M1]] = metadata !{i32 {{[0-9]*}}, metadata [[CTXT]], metadata [[NS]], i32 9} ; [ DW_TAG_imported_module ]
+// CHECK: [[M2]] = metadata !{i32 {{[0-9]*}}, metadata [[CU]], metadata [[CTXT]], i32 12} ; [ DW_TAG_imported_module ]
+// CHECK: [[M3]] = metadata !{i32 {{[0-9]*}}, metadata [[LEX:![0-9]*]], metadata [[NS]], i32 16} ; [ DW_TAG_imported_module ]
+// CHECK: [[LEX]] = metadata !{i32 {{[0-9]*}}, metadata [[FILE2]], metadata [[FUNC]], i32 15, i32 0, i32 0} ; [ DW_TAG_lexical_block ]
+// CHECK: [[M4]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[CTXT]], i32 19} ; [ DW_TAG_imported_module ]
+// CHECK: [[M5]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[FOO:![0-9]*]], i32 20} ; [ DW_TAG_imported_declaration ]
// CHECK: [[FOO]] {{.*}} ; [ DW_TAG_structure_type ] [foo] [line 5, size 0, align 0, offset 0] [fwd] [from ]
-// CHECK: [[M6]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[BAR:![0-9]*]], i32 20} ; [ DW_TAG_imported_declaration ]
+// CHECK: [[M6]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[BAR:![0-9]*]], i32 21} ; [ DW_TAG_imported_declaration ]
// CHECK: [[BAR]] {{.*}} ; [ DW_TAG_structure_type ] [bar] [line 6, {{.*}}] [from ]
-// CHECK: [[M7]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[F1]], i32 21} ; [ DW_TAG_imported_declaration ]
-// CHECK: [[M8]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[I]], i32 22} ; [ DW_TAG_imported_declaration ]
+// CHECK: [[M7]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[F1]], i32 22} ; [ DW_TAG_imported_declaration ]
+// CHECK: [[M8]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[I]], i32 23} ; [ DW_TAG_imported_declaration ]
+// CHECK: [[M9]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[BAZ:![0-9]*]], i32 24} ; [ DW_TAG_imported_declaration ]
+// CHECK: [[BAZ]] = metadata !{i32 {{[0-9]*}}, metadata [[FOOCPP]], metadata [[NS]], {{.*}} ; [ DW_TAG_typedef ] [baz] {{.*}} [from bar]
// FIXME: It is confused on win32 to generate file entry when dosish filename is given.
// REQUIRES: shell
diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp
index 1d2dc10cf2..a97c991f38 100644
--- a/test/CodeGenCXX/debug-info-template.cpp
+++ b/test/CodeGenCXX/debug-info-template.cpp
@@ -2,6 +2,9 @@
// CHECK: [[EMPTY:![0-9]*]] = metadata !{i32 0}
+// CHECK: [[FUNTYPE:![0-9]*]] = {{.*}}, metadata [[FUNARGS:![0-9]*]], i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+// CHECK: [[FUNARGS]] = metadata !{null}
+
// func<...> doesn't have any template arguments listed since we don't support
// packs yet. This could be encoded with GNU's
// DW_TAG_GNU_template_parameter_pack extension.
@@ -9,8 +12,8 @@
// CHECK: [[INT:![0-9]*]] = {{.*}} ; [ DW_TAG_base_type ] [int]
// CHECK: metadata [[TCI:![0-9]*]], i32 0, i32 1, %class.TC* @tci, null} ; [ DW_TAG_variable ] [tci]
-// CHECK: [[TC:![0-9]*]] = {{.*}}, metadata [[TCARGS:![0-9]*]]} ; [ DW_TAG_class_type ] [TC<unsigned int, 2, &glb, &foo::e, &foo::f>]
-// CHECK: [[TCARGS]] = metadata !{metadata [[TCARG1:![0-9]*]], metadata [[TCARG2:![0-9]*]], metadata [[TCARG3:![0-9]*]], metadata [[TCARG4:![0-9]*]], metadata [[TCARG5:![0-9]*]]}
+// CHECK: [[TC:![0-9]*]] = {{.*}}, metadata [[TCARGS:![0-9]*]]} ; [ DW_TAG_class_type ] [TC<unsigned int, 2, &glb, &foo::e, &foo::f, &func>]
+// CHECK: [[TCARGS]] = metadata !{metadata [[TCARG1:![0-9]*]], metadata [[TCARG2:![0-9]*]], metadata [[TCARG3:![0-9]*]], metadata [[TCARG4:![0-9]*]], metadata [[TCARG5:![0-9]*]], metadata [[TCARG6:![0-9]*]]}
//
// We seem to be missing file/line/col info on template value parameters -
// metadata supports it but it's not populated. GCC doesn't emit it either,
@@ -39,11 +42,13 @@
//
// CHECK: [[TCARG5]] = {{.*}}metadata !"b", metadata [[MEMFUNPTR:![0-9]*]], { i64, i64 } { i64 ptrtoint (void (%struct.foo*)* @_ZN3foo1fEv to i64), i64 0 }, {{.*}} ; [ DW_TAG_template_value_parameter ]
// CHECK: [[MEMFUNPTR]] = {{.*}}, metadata [[FTYPE]], metadata [[FOO]]} ; [ DW_TAG_ptr_to_member_type ]
+// CHECK: [[TCARG6]] = {{.*}}metadata !"f", metadata [[FUNPTR:![0-9]*]], void ()* @_Z4funcv, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[FUNPTR]] = {{.*}}, metadata [[FUNTYPE]]} ; [ DW_TAG_pointer_type ]
// CHECK: metadata [[TCNT:![0-9]*]], i32 0, i32 1, %class.TC.0* @tcn, null} ; [ DW_TAG_variable ] [tcn]
-// CHECK: [[TCNT:![0-9]*]] = {{.*}}, metadata [[TCNARGS:![0-9]*]]} ; [ DW_TAG_class_type ] [TC<int, -3, nullptr, nullptr, nullptr>]
-// CHECK: [[TCNARGS]] = metadata !{metadata [[TCNARG1:![0-9]*]], metadata [[TCNARG2:![0-9]*]], metadata [[TCNARG3:![0-9]*]], metadata [[TCNARG4:![0-9]*]], metadata [[TCNARG5:![0-9]*]]}
+// CHECK: [[TCNT:![0-9]*]] = {{.*}}, metadata [[TCNARGS:![0-9]*]]} ; [ DW_TAG_class_type ] [TC<int, -3, nullptr, nullptr, nullptr, nullptr>]
+// CHECK: [[TCNARGS]] = metadata !{metadata [[TCNARG1:![0-9]*]], metadata [[TCNARG2:![0-9]*]], metadata [[TCNARG3:![0-9]*]], metadata [[TCNARG4:![0-9]*]], metadata [[TCNARG5:![0-9]*]], metadata [[TCNARG6:![0-9]*]]}
// CHECK: [[TCNARG1]] = {{.*}}metadata !"T", metadata [[INT]], {{.*}} ; [ DW_TAG_template_type_parameter ]
// CHECK: [[TCNARG2]] = {{.*}}metadata !"", metadata [[INT]], i32 -3, {{.*}} ; [ DW_TAG_template_value_parameter ]
// CHECK: [[TCNARG3]] = {{.*}}metadata !"x", metadata [[INTPTR]], i8 0, {{.*}} ; [ DW_TAG_template_value_parameter ]
@@ -59,21 +64,23 @@
// naturally from the LLVM CodeGen side once we decide how to handle non-null
// member function pointers. For now, it's simpler just to emit the 'i8 0'.
//
-// CHECK: [[TCNARG5]] = {{.*}}metadata !"b", metadata [[MEMFUNPTR:![0-9]*]], i8 0, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[TCNARG5]] = {{.*}}metadata !"b", metadata [[MEMFUNPTR]], i8 0, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[TCNARG6]] = {{.*}}metadata !"f", metadata [[FUNPTR]], i8 0, {{.*}} ; [ DW_TAG_template_value_parameter ]
struct foo {
char pad[8]; // make the member pointer to 'e' a bit more interesting (nonzero)
int e;
void f();
};
-template<typename T, T, int *x, int foo::*a, void (foo::*b)()>
+template<typename T, T, int *x, int foo::*a, void (foo::*b)(), void (*f)()>
class TC {
};
int glb;
+void func();
-TC<unsigned, 2, &glb, &foo::e, &foo::f> tci;
-TC<int, -3, nullptr, nullptr, nullptr> tcn;
+TC<unsigned, 2, &glb, &foo::e, &foo::f, &func> tci;
+TC<int, -3, nullptr, nullptr, nullptr, nullptr> tcn;
template<typename ...Ts> int func() { return 0; }
int anchor = func<int>();
diff --git a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
index d03ba52649..ed7027d975 100644
--- a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
+++ b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
@@ -1,123 +1,164 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 | FileCheck -check-prefix=X64 %s
void foo(const unsigned int) {}
// CHECK: "\01?foo@@YAXI@Z"
+// X64: "\01?foo@@YAXI@Z"
void foo(const double) {}
// CHECK: "\01?foo@@YAXN@Z"
+// X64: "\01?foo@@YAXN@Z"
void bar(const volatile double) {}
// CHECK: "\01?bar@@YAXN@Z"
+// X64: "\01?bar@@YAXN@Z"
void foo_pad(char * x) {}
// CHECK: "\01?foo_pad@@YAXPAD@Z"
+// X64: "\01?foo_pad@@YAXPEAD@Z"
void foo_pbd(const char * x) {}
// CHECK: "\01?foo_pbd@@YAXPBD@Z"
+// X64: "\01?foo_pbd@@YAXPEBD@Z"
void foo_pcd(volatile char * x) {}
// CHECK: "\01?foo_pcd@@YAXPCD@Z"
+// X64: "\01?foo_pcd@@YAXPECD@Z"
void foo_qad(char * const x) {}
// CHECK: "\01?foo_qad@@YAXQAD@Z"
+// X64: "\01?foo_qad@@YAXQEAD@Z"
void foo_rad(char * volatile x) {}
// CHECK: "\01?foo_rad@@YAXRAD@Z"
+// X64: "\01?foo_rad@@YAXREAD@Z"
void foo_sad(char * const volatile x) {}
// CHECK: "\01?foo_sad@@YAXSAD@Z"
+// X64: "\01?foo_sad@@YAXSEAD@Z"
void foo_papad(char ** x) {}
// CHECK: "\01?foo_papad@@YAXPAPAD@Z"
+// X64: "\01?foo_papad@@YAXPEAPEAD@Z"
void foo_papbd(char const ** x) {}
// CHECK: "\01?foo_papbd@@YAXPAPBD@Z"
+// X64: "\01?foo_papbd@@YAXPEAPEBD@Z"
void foo_papcd(char volatile ** x) {}
// CHECK: "\01?foo_papcd@@YAXPAPCD@Z"
+// X64: "\01?foo_papcd@@YAXPEAPECD@Z"
void foo_pbqad(char * const* x) {}
// CHECK: "\01?foo_pbqad@@YAXPBQAD@Z"
+// X64: "\01?foo_pbqad@@YAXPEBQEAD@Z"
void foo_pcrad(char * volatile* x) {}
// CHECK: "\01?foo_pcrad@@YAXPCRAD@Z"
+// X64: "\01?foo_pcrad@@YAXPECREAD@Z"
void foo_qapad(char ** const x) {}
// CHECK: "\01?foo_qapad@@YAXQAPAD@Z"
+// X64: "\01?foo_qapad@@YAXQEAPEAD@Z"
void foo_rapad(char ** volatile x) {}
// CHECK: "\01?foo_rapad@@YAXRAPAD@Z"
+// X64: "\01?foo_rapad@@YAXREAPEAD@Z"
void foo_pbqbd(const char * const* x) {}
// CHECK: "\01?foo_pbqbd@@YAXPBQBD@Z"
+// X64: "\01?foo_pbqbd@@YAXPEBQEBD@Z"
void foo_pbqcd(volatile char * const* x) {}
// CHECK: "\01?foo_pbqcd@@YAXPBQCD@Z"
+// X64: "\01?foo_pbqcd@@YAXPEBQECD@Z"
void foo_pcrbd(const char * volatile* x) {}
// CHECK: "\01?foo_pcrbd@@YAXPCRBD@Z"
+// X64: "\01?foo_pcrbd@@YAXPECREBD@Z"
void foo_pcrcd(volatile char * volatile* x) {}
// CHECK: "\01?foo_pcrcd@@YAXPCRCD@Z"
+// X64: "\01?foo_pcrcd@@YAXPECRECD@Z"
void foo_aad(char &x) {}
// CHECK: "\01?foo_aad@@YAXAAD@Z"
+// X64: "\01?foo_aad@@YAXAEAD@Z"
void foo_abd(const char &x) {}
// CHECK: "\01?foo_abd@@YAXABD@Z"
+// X64: "\01?foo_abd@@YAXAEBD@Z"
void foo_aapad(char *&x) {}
// CHECK: "\01?foo_aapad@@YAXAAPAD@Z"
+// X64: "\01?foo_aapad@@YAXAEAPEAD@Z"
void foo_aapbd(const char *&x) {}
// CHECK: "\01?foo_aapbd@@YAXAAPBD@Z"
+// X64: "\01?foo_aapbd@@YAXAEAPEBD@Z"
void foo_abqad(char * const &x) {}
// CHECK: "\01?foo_abqad@@YAXABQAD@Z"
+// X64: "\01?foo_abqad@@YAXAEBQEAD@Z"
void foo_abqbd(const char * const &x) {}
// CHECK: "\01?foo_abqbd@@YAXABQBD@Z"
+// X64: "\01?foo_abqbd@@YAXAEBQEBD@Z"
void foo_aay144h(int (&x)[5][5]) {}
// CHECK: "\01?foo_aay144h@@YAXAAY144H@Z"
+// X64: "\01?foo_aay144h@@YAXAEAY144H@Z"
void foo_aay144cbh(const int (&x)[5][5]) {}
// CHECK: "\01?foo_aay144cbh@@YAXAAY144$$CBH@Z"
+// X64: "\01?foo_aay144cbh@@YAXAEAY144$$CBH@Z"
void foo_qay144h(int (&&x)[5][5]) {}
// CHECK: "\01?foo_qay144h@@YAX$$QAY144H@Z"
+// X64: "\01?foo_qay144h@@YAX$$QEAY144H@Z"
void foo_qay144cbh(const int (&&x)[5][5]) {}
// CHECK: "\01?foo_qay144cbh@@YAX$$QAY144$$CBH@Z"
+// X64: "\01?foo_qay144cbh@@YAX$$QEAY144$$CBH@Z"
void foo_p6ahxz(int x()) {}
// CHECK: "\01?foo_p6ahxz@@YAXP6AHXZ@Z"
+// X64: "\01?foo_p6ahxz@@YAXP6AHXZ@Z"
void foo_a6ahxz(int (&x)()) {}
// CHECK: "\01?foo_a6ahxz@@YAXA6AHXZ@Z"
+// X64: "\01?foo_a6ahxz@@YAXA6AHXZ@Z"
void foo_q6ahxz(int (&&x)()) {}
// CHECK: "\01?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
+// X64: "\01?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
void foo_qay04h(int x[5][5]) {}
// CHECK: "\01?foo_qay04h@@YAXQAY04H@Z"
+// X64: "\01?foo_qay04h@@YAXQEAY04H@Z"
void foo_qay04cbh(const int x[5][5]) {}
// CHECK: "\01?foo_qay04cbh@@YAXQAY04$$CBH@Z"
+// X64: "\01?foo_qay04cbh@@YAXQEAY04$$CBH@Z"
typedef double Vector[3];
void foo(Vector*) {}
// CHECK: "\01?foo@@YAXPAY02N@Z"
+// X64: "\01?foo@@YAXPEAY02N@Z"
void foo(Vector) {}
// CHECK: "\01?foo@@YAXQAN@Z"
+// X64: "\01?foo@@YAXQEAN@Z"
void foo_const(const Vector) {}
// CHECK: "\01?foo_const@@YAXQBN@Z"
+// X64: "\01?foo_const@@YAXQEBN@Z"
void foo_volatile(volatile Vector) {}
// CHECK: "\01?foo_volatile@@YAXQCN@Z"
+// X64: "\01?foo_volatile@@YAXQECN@Z"
void foo(Vector*, const Vector, const double) {}
// CHECK: "\01?foo@@YAXPAY02NQBNN@Z"
+// X64: "\01?foo@@YAXPEAY02NQEBNN@Z"
diff --git a/test/CodeGenCXX/mangle-ms-templates.cpp b/test/CodeGenCXX/mangle-ms-templates.cpp
index 10e68248dc..c52b6b4b7a 100644
--- a/test/CodeGenCXX/mangle-ms-templates.cpp
+++ b/test/CodeGenCXX/mangle-ms-templates.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fms-extensions -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
template<typename T>
class Class {
@@ -33,65 +34,87 @@ class BoolTemplate<true> {
void template_mangling() {
Class<Typename> c1;
// CHECK: call {{.*}} @"\01??0?$Class@VTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@VTypename@@@@QEAA@XZ"
Class<const Typename> c1_const;
// CHECK: call {{.*}} @"\01??0?$Class@$$CBVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$CBVTypename@@@@QEAA@XZ"
Class<volatile Typename> c1_volatile;
// CHECK: call {{.*}} @"\01??0?$Class@$$CCVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$CCVTypename@@@@QEAA@XZ"
Class<const volatile Typename> c1_cv;
// CHECK: call {{.*}} @"\01??0?$Class@$$CDVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$CDVTypename@@@@QEAA@XZ"
Class<Nested<Typename> > c2;
// CHECK: call {{.*}} @"\01??0?$Class@V?$Nested@VTypename@@@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@V?$Nested@VTypename@@@@@@QEAA@XZ"
Class<int * const> c_intpc;
// CHECK: call {{.*}} @"\01??0?$Class@QAH@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@QEAH@@QEAA@XZ"
Class<int()> c_ft;
// CHECK: call {{.*}} @"\01??0?$Class@$$A6AHXZ@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$A6AHXZ@@QEAA@XZ"
Class<int[]> c_inti;
// CHECK: call {{.*}} @"\01??0?$Class@$$BY0A@H@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$BY0A@H@@QEAA@XZ"
Class<int[5]> c_int5;
// CHECK: call {{.*}} @"\01??0?$Class@$$BY04H@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$BY04H@@QEAA@XZ"
Class<const int[5]> c_intc5;
// CHECK: call {{.*}} @"\01??0?$Class@$$BY04$$CBH@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$BY04$$CBH@@QEAA@XZ"
Class<int * const[5]> c_intpc5;
// CHECK: call {{.*}} @"\01??0?$Class@$$BY04QAH@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$BY04QEAH@@QEAA@XZ"
BoolTemplate<false> _false;
// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QEAA@XZ"
BoolTemplate<true> _true;
// PR13158
_true.Foo(1);
// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$00@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$BoolTemplate@$00@@QEAA@XZ"
// CHECK: call {{.*}} @"\01??$Foo@H@?$BoolTemplate@$00@@QAEXH@Z"
+// X64: call {{.*}} @"\01??$Foo@H@?$BoolTemplate@$00@@QEAAXH@Z"
IntTemplate<0> zero;
// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0A@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0A@@@QEAA@XZ"
IntTemplate<5> five;
// CHECK: call {{.*}} @"\01??0?$IntTemplate@$04@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$04@@QEAA@XZ"
IntTemplate<11> eleven;
// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0L@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0L@@@QEAA@XZ"
IntTemplate<256> _256;
// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0BAA@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0BAA@@@QEAA@XZ"
IntTemplate<513> _513;
// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0CAB@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0CAB@@@QEAA@XZ"
IntTemplate<1026> _1026;
// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0EAC@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0EAC@@@QEAA@XZ"
IntTemplate<65535> ffff;
// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0PPPP@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0PPPP@@@QEAA@XZ"
}
namespace space {
template<class T> const T& foo(const T& l) { return l; }
}
// CHECK: "\01??$foo@H@space@@YAABHABH@Z"
+// X64: "\01??$foo@H@space@@YAAEBHAEBH@Z"
void use() {
space::foo(42);
@@ -108,4 +131,5 @@ void FunctionPointerTemplate() {
void spam() {
FunctionPointerTemplate<spam>();
// CHECK: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
+// X64: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
}
diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp
index 1b98a84823..3f80e54f43 100644
--- a/test/CodeGenCXX/mangle-ms.cpp
+++ b/test/CodeGenCXX/mangle-ms.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
-// RUN: %clang_cc1 -fms-compatibility -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
+// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
// CHECK: @"\01?a@@3HA"
// CHECK: @"\01?b@N@@3HA"
@@ -33,6 +33,7 @@ namespace N {
static int c;
int _c(void) {return N::anonymous + c;}
// CHECK: @"\01?_c@@YAHXZ"
+// X64: @"\01?_c@@YAHXZ"
class foo {
static const short d;
@@ -43,15 +44,19 @@ public:
int operator+(int a);
foo(){}
//CHECK: @"\01??0foo@@QAE@XZ"
+//X64: @"\01??0foo@@QEAA@XZ"
~foo(){}
//CHECK: @"\01??1foo@@QAE@XZ"
+//X64: @"\01??1foo@@QEAA@XZ
foo(int i){}
//CHECK: @"\01??0foo@@QAE@H@Z"
+//X64: @"\01??0foo@@QEAA@H@Z"
foo(char *q){}
//CHECK: @"\01??0foo@@QAE@PAD@Z"
+//X64: @"\01??0foo@@QEAA@PEAD@Z"
static foo* static_method() { return 0; }
@@ -77,12 +82,15 @@ enum quux {
foo bar() { return foo(); }
//CHECK: @"\01?bar@@YA?AVfoo@@XZ"
+//X64: @"\01?bar@@YA?AVfoo@@XZ"
int foo::operator+(int a) {
//CHECK: @"\01??Hfoo@@QAEHH@Z"
+//X64: @"\01??Hfoo@@QEAAHH@Z"
foo::static_method();
//CHECK: @"\01?static_method@foo@@SAPAV1@XZ"
+//X64: @"\01?static_method@foo@@SAPEAV1@XZ"
bar();
return a;
}
@@ -109,6 +117,7 @@ int (foo2::*l)(int);
static void __stdcall alpha(float a, double b) throw() {}
bool __fastcall beta(long long a, wchar_t b) throw(signed char, unsigned char) {
// CHECK: @"\01?beta@@YI_N_J_W@Z"
+// X64: @"\01?beta@@YA_N_J_W@Z"
alpha(0.f, 0.0);
return false;
}
@@ -119,17 +128,21 @@ bool __fastcall beta(long long a, wchar_t b) throw(signed char, unsigned char) {
// Make sure tag-type mangling works.
void gamma(class foo, struct bar, union baz, enum quux) {}
// CHECK: @"\01?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
+// X64: @"\01?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
// Make sure pointer/reference-type mangling works.
void delta(int * const a, const long &) {}
// CHECK: @"\01?delta@@YAXQAHABJ@Z"
+// X64: @"\01?delta@@YAXQEAHAEBJ@Z"
// Array mangling.
void epsilon(int a[][10][20]) {}
// CHECK: @"\01?epsilon@@YAXQAY19BE@H@Z"
+// X64: @"\01?epsilon@@YAXQEAY19BE@H@Z"
void zeta(int (*)(int, int)) {}
// CHECK: @"\01?zeta@@YAXP6AHHH@Z@Z"
+// X64: @"\01?zeta@@YAXP6AHHH@Z@Z"
// Blocks mangling (Clang extension). A block should be mangled slightly
// differently from a similar function pointer.
@@ -158,6 +171,7 @@ void operator_new_delete() {
void (redundant_parens)();
void redundant_parens_use() { redundant_parens(); }
// CHECK: @"\01?redundant_parens@@YAXXZ"
+// X64: @"\01?redundant_parens@@YAXXZ"
// PR13047
typedef double RGB[3];
@@ -169,10 +183,12 @@ extern RGB const ((color4)[5]) = {};
// PR12603
enum E {};
// CHECK: "\01?fooE@@YA?AW4E@@XZ"
+// X64: "\01?fooE@@YA?AW4E@@XZ"
E fooE() { return E(); }
class X {};
// CHECK: "\01?fooX@@YA?AVX@@XZ"
+// X64: "\01?fooX@@YA?AVX@@XZ"
X fooX() { return X(); }
namespace PR13182 {
diff --git a/test/Format/diagnostic.cpp b/test/Format/diagnostic.cpp
deleted file mode 100644
index 2e930ee5b7..0000000000
--- a/test/Format/diagnostic.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: clang-format 2>&1 >/dev/null %s |FileCheck %s
-
-}
-// CHECK: diagnostic.cpp:[[@LINE-1]]:1: error: unexpected '}'
diff --git a/test/Index/comment-to-html-xml-conversion.cpp b/test/Index/comment-to-html-xml-conversion.cpp
index c770ca8d30..ce64dd40b9 100644
--- a/test/Index/comment-to-html-xml-conversion.cpp
+++ b/test/Index/comment-to-html-xml-conversion.cpp
@@ -741,11 +741,11 @@ int comment_to_xml_conversion_12;
/// Aaa.
namespace comment_to_xml_conversion_13 {
-// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:11: Namespace=comment_to_xml_conversion_13:{{.*}} FullCommentAsXML=[<Namespace file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="11"><Name>comment_to_xml_conversion_13</Name><USR>c:@N@comment_to_xml_conversion_13</USR><Declaration>namespace comment_to_xml_conversion_13 {}</Declaration><Abstract><Para> Aaa.</Para></Abstract></Namespace>]
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:11: Namespace=comment_to_xml_conversion_13:{{.*}} FullCommentAsXML=[<Namespace file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="11"><Name>comment_to_xml_conversion_13</Name><USR>c:@N@comment_to_xml_conversion_13</USR><Declaration>namespace comment_to_xml_conversion_13 {\n}</Declaration><Abstract><Para> Aaa.</Para></Abstract></Namespace>]
/// Aaa.
namespace comment_to_xml_conversion_14 {
-// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:13: Namespace=comment_to_xml_conversion_14:{{.*}} FullCommentAsXML=[<Namespace file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="13"><Name>comment_to_xml_conversion_14</Name><USR>c:@N@comment_to_xml_conversion_13@N@comment_to_xml_conversion_14</USR><Declaration>namespace comment_to_xml_conversion_14 {}</Declaration><Abstract><Para> Aaa.</Para></Abstract></Namespace>]
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:13: Namespace=comment_to_xml_conversion_14:{{.*}} FullCommentAsXML=[<Namespace file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="13"><Name>comment_to_xml_conversion_14</Name><USR>c:@N@comment_to_xml_conversion_13@N@comment_to_xml_conversion_14</USR><Declaration>namespace comment_to_xml_conversion_14 {\n}</Declaration><Abstract><Para> Aaa.</Para></Abstract></Namespace>]
}
}
diff --git a/test/Lexer/char-literal.cpp b/test/Lexer/char-literal.cpp
index b2fab34e44..1cd14a9b01 100644
--- a/test/Lexer/char-literal.cpp
+++ b/test/Lexer/char-literal.cpp
@@ -36,8 +36,4 @@ char16_t p[2] = u"\U0000FFFF";
char16_t q[2] = u"\U00010000";
#ifdef __cplusplus
// expected-error@-2 {{too long}}
-#else
-// FIXME: The above should be accepted in C11 mode.
-// expected-error@-6 {{must be an initializer list}}
-// expected-error@-6 {{must be an initializer list}}
#endif
diff --git a/test/Misc/ast-dump-templates.cpp b/test/Misc/ast-dump-templates.cpp
index 7e28da95a1..b7aeca8d55 100644
--- a/test/Misc/ast-dump-templates.cpp
+++ b/test/Misc/ast-dump-templates.cpp
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -ast-print %s > %t
// RUN: FileCheck < %t %s -check-prefix=CHECK1
// RUN: FileCheck < %t %s -check-prefix=CHECK2
+// RUN: %clang_cc1 -ast-dump %s | FileCheck --check-prefix=DUMP %s
template <int X, typename Y, int Z = 5>
struct foo {
@@ -37,3 +38,14 @@ void baz() {
// Template definition - bar
// CHECK1: template <int A, typename B> B bar()
// CHECK2: template <int A, typename B> B bar()
+
+namespace test2 {
+void func(int);
+void func(float);
+template<typename T>
+void tmpl() {
+ func(T());
+}
+
+// DUMP: UnresolvedLookupExpr {{.*}} <col:3> '<overloaded function type>' lvalue (ADL) = 'func'
+}
diff --git a/test/Modules/objc-categories.m b/test/Modules/objc-categories.m
index 81fb28bafb..f08b13a78a 100644
--- a/test/Modules/objc-categories.m
+++ b/test/Modules/objc-categories.m
@@ -10,6 +10,7 @@
// expected-note@Inputs/category_left.h:14 {{previous definition}}
// expected-warning@Inputs/category_right.h:11 {{duplicate definition of category}}
+// expected-note@Inputs/category_top.h:1 {{receiver is instance of class declared here}}
@interface Foo(Source)
-(void)source;
diff --git a/test/OpenMP/predefined_macro.c b/test/OpenMP/predefined_macro.c
index cf6c0cc611..3a81186209 100644
--- a/test/OpenMP/predefined_macro.c
+++ b/test/OpenMP/predefined_macro.c
@@ -31,4 +31,3 @@
#error "_OPENMP macro is defined without -fopenmp option"
#endif // _OPENMP
#endif // FOPENMP
-
diff --git a/test/OpenMP/threadprivate_messages.cpp b/test/OpenMP/threadprivate_messages.cpp
index 0c448b2ef2..1bfba6d864 100644
--- a/test/OpenMP/threadprivate_messages.cpp
+++ b/test/OpenMP/threadprivate_messages.cpp
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 %s
-#pragma omp threadprivate // expected-error {{expected '(' after 'threadprivate'}}
-#pragma omp threadprivate( // expected-error {{expected unqualified-id}}
-#pragma omp threadprivate() // expected-error {{expected unqualified-id}}
+#pragma omp threadprivate // expected-error {{expected '(' after 'threadprivate'}} expected-error {{expected identifier}}
+#pragma omp threadprivate( // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp threadprivate() // expected-error {{expected identifier}}
#pragma omp threadprivate(1) // expected-error {{expected unqualified-id}}
struct CompleteSt{
int a;
@@ -11,27 +11,27 @@ struct CompleteSt{
struct CompleteSt1{
#pragma omp threadprivate(1) // expected-error {{expected unqualified-id}}
int a;
-} d; // expected-note {{forward declaration of 'd'}}
+} d; // expected-note {{'d' defined here}}
-int a; // expected-note {{forward declaration of 'a'}}
+int a; // expected-note {{'a' defined here}}
#pragma omp threadprivate(a)
#pragma omp threadprivate(u) // expected-error {{use of undeclared identifier 'u'}}
#pragma omp threadprivate(d, a) // expected-error {{'#pragma omp threadprivate' must precede all references to variable 'a'}}
int foo() { // expected-note {{declared here}}
static int l;
-#pragma omp threadprivate(l)) // expected-warning {{extra tokens at end of '#pragma omp threadprivate' are ignored}}
+#pragma omp threadprivate(l)) // expected-warning {{extra tokens at the end of '#pragma omp threadprivate' are ignored}}
return (a);
}
-#pragma omp threadprivate a // expected-error {{expected '(' after 'threadprivate'}}
+#pragma omp threadprivate a // expected-error {{expected '(' after 'threadprivate'}} expected-error {{'#pragma omp threadprivate' must precede all references to variable 'a'}}
#pragma omp threadprivate(d // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{'#pragma omp threadprivate' must precede all references to variable 'd'}}
-#pragma omp threadprivate(d))
+#pragma omp threadprivate(d)) // expected-error {{'#pragma omp threadprivate' must precede all references to variable 'd'}} expected-warning {{extra tokens at the end of '#pragma omp threadprivate' are ignored}}
int x, y;
-#pragma omp threadprivate(x)) // expected-warning {{extra tokens at end of '#pragma omp threadprivate' are ignored}}
-#pragma omp threadprivate(y)), // expected-warning {{extra tokens at end of '#pragma omp threadprivate' are ignored}}
+#pragma omp threadprivate(x)) // expected-warning {{extra tokens at the end of '#pragma omp threadprivate' are ignored}}
+#pragma omp threadprivate(y)), // expected-warning {{extra tokens at the end of '#pragma omp threadprivate' are ignored}}
#pragma omp threadprivate(a,d) // expected-error {{'#pragma omp threadprivate' must precede all references to variable 'a'}} expected-error {{'#pragma omp threadprivate' must precede all references to variable 'd'}}
-#pragma omp threadprivate(d.a) // expected-error {{expected unqualified-id}}
+#pragma omp threadprivate(d.a) // expected-error {{expected identifier}}
#pragma omp threadprivate((float)a) // expected-error {{expected unqualified-id}}
int foa;
#pragma omp threadprivate(faa) // expected-error {{use of undeclared identifier 'faa'; did you mean 'foa'?}}
@@ -41,31 +41,31 @@ int foa;
struct IncompleteSt; // expected-note {{forward declaration of 'IncompleteSt'}}
extern IncompleteSt e;
-#pragma omp threadprivate (e) // expected-error {{a threadprivate variable must not have incomplete type 'IncompleteSt'}}
+#pragma omp threadprivate (e) // expected-error {{threadprivate variable with incomplete type 'IncompleteSt'}}
-int &f = a; // expected-note {{forward declaration of 'f'}}
-#pragma omp threadprivate (f) // expected-error {{arguments of '#pragma omp threadprivate' cannot be of reference type 'int &'}}
+int &f = a; // expected-note {{'f' defined here}}
+#pragma omp threadprivate (f) // expected-error {{arguments of '#pragma omp threadprivate' cannot be of reference type}}
class Class {
private:
int a; // expected-note {{declared here}}
- static int b;
+ static int b; // expected-note {{'b' declared here}}
Class() : a(0){}
public:
Class (int aaa) : a(aaa) {}
#pragma omp threadprivate (b, a) // expected-error {{'a' is not a global variable, static local variable or static data member}}
} g(10);
#pragma omp threadprivate (b) // expected-error {{use of undeclared identifier 'b'}}
-#pragma omp threadprivate (Class::b) // expected-error {{expected unqualified-id}}
+#pragma omp threadprivate (Class::b) // expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'Class::b' variable declaration}}
#pragma omp threadprivate (g)
namespace ns {
- int m;
+ int m; // expected-note 2 {{'m' defined here}}
#pragma omp threadprivate (m)
}
#pragma omp threadprivate (m) // expected-error {{use of undeclared identifier 'm'}}
-#pragma omp threadprivate (ns::m) // expected-error {{expected unqualified-id}}
-#pragma omp threadprivate (ns:m) // expected-error {{expected unqualified-id}}
+#pragma omp threadprivate (ns::m) // expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'ns::m' variable declaration}}
+#pragma omp threadprivate (ns:m) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}} expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'ns::m' variable declaration}}
const int h = 12;
const volatile int i = 10;
@@ -84,26 +84,30 @@ class TempClass {
};
#pragma omp threadprivate (s) // expected-error {{use of undeclared identifier 's'}}
-static __thread int t; // expected-note {{forward declaration of 't'}}
+static __thread int t; // expected-note {{'t' defined here}}
#pragma omp threadprivate (t) // expected-error {{variable 't' cannot be threadprivate because it is thread-local}}
int o; // expected-note {{candidate found by name lookup is 'o'}}
+#pragma omp threadprivate (o)
namespace {
int o; // expected-note {{candidate found by name lookup is '<anonymous namespace>::o'}}
+#pragma omp threadprivate (o)
+#pragma omp threadprivate (o) // expected-error {{'#pragma omp threadprivate' must precede all references to variable '<anonymous namespace>::o'}}
}
#pragma omp threadprivate (o) // expected-error {{reference to 'o' is ambiguous}}
+#pragma omp threadprivate (::o) // expected-error {{'#pragma omp threadprivate' must precede all references to variable 'o'}}
-int main(int argc, char **argv) { // expected-note {{forward declaration of 'argc'}}
+int main(int argc, char **argv) { // expected-note {{'argc' defined here}}
- int x, y = argc; // expected-note {{forward declaration of 'y'}}
+ int x, y = argc; // expected-note {{'y' defined here}}
static double d1;
static double d2;
- static double d3; // expected-note {{forward declaration of 'd3'}}
+ static double d3; // expected-note {{'d3' defined here}}
d.a = a;
d2++;
;
-#pragma omp threadprivate(argc+y) // expected-error {{expected unqualified-id}}
+#pragma omp threadprivate(argc+y) // expected-error {{expected identifier}}
#pragma omp threadprivate(argc,y) // expected-error 2 {{arguments of '#pragma omp threadprivate' must have static storage duration}}
#pragma omp threadprivate(d2) // expected-error {{'#pragma omp threadprivate' must precede all references to variable 'd2'}}
#pragma omp threadprivate(d1)
diff --git a/test/PCH/chain-categories2.m b/test/PCH/chain-categories2.m
index f230bf9348..50eea2a560 100644
--- a/test/PCH/chain-categories2.m
+++ b/test/PCH/chain-categories2.m
@@ -45,6 +45,7 @@
#else
//===----------------------------------------------------------------------===//
+// expected-note@30 {{receiver is instance of class declared here}}
void f(I* i) {
[i meth]; // expected-warning {{not found}}
}
diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c
index 9671f7e232..b3af46e575 100644
--- a/test/Preprocessor/init.c
+++ b/test/Preprocessor/init.c
@@ -2688,6 +2688,14 @@
// X86_64-LINUX:#define __x86_64 1
// X86_64-LINUX:#define __x86_64__ 1
//
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=sparc64-none-none < /dev/null | FileCheck -check-prefix SPARCV9 %s
+// SPARCV9:#define __INTMAX_TYPE__ long int
+// SPARCV9:#define __INTPTR_TYPE__ long int
+// SPARCV9:#define __LONG_MAX__ 9223372036854775807L
+// SPARCV9:#define __LP64__ 1
+// SPARCV9:#define __SIZEOF_LONG__ 8
+// SPARCV9:#define __SIZEOF_POINTER__ 8
+//
// RUN: %clang_cc1 -x c++ -triple i686-pc-linux-gnu -fobjc-runtime=gcc -E -dM < /dev/null | FileCheck -check-prefix GNUSOURCE %s
// GNUSOURCE:#define _GNU_SOURCE 1
//
diff --git a/test/Sema/builtins-aarch64.c b/test/Sema/builtins-aarch64.c
index 03e03343eb..b0557532fa 100644
--- a/test/Sema/builtins-aarch64.c
+++ b/test/Sema/builtins-aarch64.c
@@ -1,4 +1,9 @@
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -DTEST1 -fsyntax-only -verify %s
+
+#ifdef TEST1
+void __clear_cache(void *start, void *end);
+#endif
void test_clear_cache_chars(char *start, char *end) {
__clear_cache(start, end);
diff --git a/test/Sema/builtins-arm.c b/test/Sema/builtins-arm.c
index 7b48af155e..3ac1da0aa9 100644
--- a/test/Sema/builtins-arm.c
+++ b/test/Sema/builtins-arm.c
@@ -1,15 +1,15 @@
-// RUN: %clang_cc1 -triple armv7 -fsyntax-only -verify -DTEST0 %s
-// RUN: %clang_cc1 -triple armv7 -fsyntax-only -verify -DTEST1 %s
+// RUN: %clang_cc1 -triple armv7 -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple armv7 -target-abi apcs-gnu \
-// RUN: -fsyntax-only -verify -DTEST1 %s
+// RUN: -fsyntax-only -verify %s
-#ifdef TEST0
-void __clear_cache(char*, char*);
-#endif
+void f(void *a, void *b) {
+ __clear_cache(); // expected-error {{too few arguments to function call, expected 2, have 0}} // expected-note {{'__clear_cache' is a builtin with type 'void (void *, void *)}}
+ __clear_cache(a); // expected-error {{too few arguments to function call, expected 2, have 1}}
+ __clear_cache(a, b);
+}
-#ifdef TEST1
+void __clear_cache(char*, char*); // expected-error {{conflicting types for '__clear_cache'}}
void __clear_cache(void*, void*);
-#endif
#if defined(__ARM_PCS) || defined(__ARM_EABI__)
// va_list on ARM AAPCS is struct { void* __ap }.
diff --git a/test/Sema/ms-wchar.c b/test/Sema/ms-wchar.c
index 52a736c640..febaf283b3 100644
--- a/test/Sema/ms-wchar.c
+++ b/test/Sema/ms-wchar.c
@@ -12,4 +12,7 @@ __wchar_t g = L'a'; // expected-note {{previous}}
unsigned short g; // expected-error {{redefinition of 'g' with a different type: 'unsigned short' vs '__wchar_t'}}
// The type of a wide string literal is actually not __wchar_t.
-__wchar_t s[] = L"Hello world!"; // expected-error {{array initializer must be an initializer list}}
+__wchar_t s[] = L"Hello world!"; // expected-error-re {{array initializer must be an initializer list$}}
+
+// Do not suggest initializing with a string here, because it would not work.
+__wchar_t t[] = 1; // expected-error-re {{array initializer must be an initializer list$}}
diff --git a/test/Sema/offsetof-64.c b/test/Sema/offsetof-64.c
new file mode 100644
index 0000000000..1cabec9842
--- /dev/null
+++ b/test/Sema/offsetof-64.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-linux-gnu
+// expected-no-diagnostics
+
+// PR15216
+// Don't crash when taking computing the offset of structs with large arrays.
+const unsigned long Size = (1l << 62);
+
+struct Chunk {
+ char padding[Size];
+ char more_padding[1][Size];
+ char data;
+};
+
+int test1 = __builtin_offsetof(struct Chunk, data);
+
diff --git a/test/Sema/offsetof.c b/test/Sema/offsetof.c
index 46fb515c7f..9e876ad589 100644
--- a/test/Sema/offsetof.c
+++ b/test/Sema/offsetof.c
@@ -69,3 +69,4 @@ int test4 = __builtin_offsetof(Array, array);
int test5() {
return __builtin_offsetof(Array, array[*(int*)0]); // expected-warning{{indirection of non-volatile null pointer}} expected-note{{__builtin_trap}}
}
+
diff --git a/test/Sema/string-init.c b/test/Sema/string-init.c
new file mode 100644
index 0000000000..96ee360e44
--- /dev/null
+++ b/test/Sema/string-init.c
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -std=c11 -fsyntax-only -triple x86_64-pc-linux -verify %s
+
+// Note: these match the types specified by the target above.
+typedef int wchar_t;
+typedef unsigned short char16_t;
+typedef unsigned int char32_t;
+
+void f() {
+ char a1[] = "a"; // No error.
+ char a2[] = u8"a"; // No error.
+ char a3[] = u"a"; // expected-error{{initializing char array with wide string literal}}
+ char a4[] = U"a"; // expected-error{{initializing char array with wide string literal}}
+ char a5[] = L"a"; // expected-error{{initializing char array with wide string literal}}
+
+ wchar_t b1[] = "a"; // expected-error{{initializing wide char array with non-wide string literal}}
+ wchar_t b2[] = u8"a"; // expected-error{{initializing wide char array with non-wide string literal}}
+ wchar_t b3[] = u"a"; // expected-error{{initializing wide char array with incompatible wide string literal}}
+ wchar_t b4[] = U"a"; // expected-error{{initializing wide char array with incompatible wide string literal}}
+ wchar_t b5[] = L"a"; // No error.
+
+ char16_t c1[] = "a"; // expected-error{{initializing wide char array with non-wide string literal}}
+ char16_t c2[] = u8"a"; // expected-error{{initializing wide char array with non-wide string literal}}
+ char16_t c3[] = u"a"; // No error.
+ char16_t c4[] = U"a"; // expected-error{{initializing wide char array with incompatible wide string literal}}
+ char16_t c5[] = L"a"; // expected-error{{initializing wide char array with incompatible wide string literal}}
+
+ char32_t d1[] = "a"; // expected-error{{initializing wide char array with non-wide string literal}}
+ char32_t d2[] = u8"a"; // expected-error{{initializing wide char array with non-wide string literal}}
+ char32_t d3[] = u"a"; // expected-error{{initializing wide char array with incompatible wide string literal}}
+ char32_t d4[] = U"a"; // No error.
+ char32_t d5[] = L"a"; // expected-error{{initializing wide char array with incompatible wide string literal}}
+
+ int e1[] = "a"; // expected-error{{initializing wide char array with non-wide string literal}}
+ int e2[] = u8"a"; // expected-error{{initializing wide char array with non-wide string literal}}
+ int e3[] = u"a"; // expected-error{{initializing wide char array with incompatible wide string literal}}
+ int e4[] = U"a"; // expected-error{{initializing wide char array with incompatible wide string literal}}
+ int e5[] = L"a"; // No error.
+
+ long f1[] = "a"; // expected-error{{array initializer must be an initializer list}}
+ long f2[] = u8"a"; // expected-error{{array initializer must be an initializer list}}}
+ long f3[] = u"a"; // expected-error{{array initializer must be an initializer list}}
+ long f4[] = U"a"; // expected-error{{array initializer must be an initializer list}}
+ long f5[] = L"a"; // expected-error{{array initializer must be an initializer list}}
+}
+
+void g() {
+ char a[] = 1; // expected-error{{array initializer must be an initializer list or string literal}}
+ wchar_t b[] = 1; // expected-error{{array initializer must be an initializer list or wide string literal}}
+ char16_t c[] = 1; // expected-error{{array initializer must be an initializer list or wide string literal}}
+ char32_t d[] = 1; // expected-error{{array initializer must be an initializer list or wide string literal}}
+}
diff --git a/test/Sema/warn-documentation.m b/test/Sema/warn-documentation.m
index 14e0c347e3..2720480509 100644
--- a/test/Sema/warn-documentation.m
+++ b/test/Sema/warn-documentation.m
@@ -176,3 +176,24 @@ struct S;
// expected-warning@+1 {{unknown command tag name}}
/// \t bbb IS_DOXYGEN_END
int FooBar();
+
+// rdar://13836387
+/** \brief Module handling the incoming notifications from the system.
+ *
+ * This includes:
+ * - Network Reachability
+ * - Power State
+ * - Low Disk
+ */
+@interface BRC : NSObject
+- (void)removeReach:(NSObject*)observer;
+@end
+
+@implementation BRC : NSObject
+- (void)removeReach:(NSObject*)observer // expected-note {{previous declaration is here}}
+{
+}
+- (void)removeReach:(NSObject*)observer // expected-error {{duplicate declaration of method 'removeReach:'}}
+{
+}
+@end
diff --git a/test/Sema/wchar.c b/test/Sema/wchar.c
index 816245f3c0..13c2f5855d 100644
--- a/test/Sema/wchar.c
+++ b/test/Sema/wchar.c
@@ -19,6 +19,6 @@ int check_wchar_size[sizeof(*L"") == sizeof(wchar_t) ? 1 : -1];
void foo() {
WCHAR_T_TYPE t1[] = L"x";
wchar_t tab[] = L"x";
- WCHAR_T_TYPE t2[] = "x"; // expected-error {{initializer}}
- char t3[] = L"x"; // expected-error {{initializer}}
+ WCHAR_T_TYPE t2[] = "x"; // expected-error {{initializing wide char array with non-wide string literal}}
+ char t3[] = L"x"; // expected-error {{initializing char array with wide string literal}}
}
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index 09a9cb5dd8..97b0b91b99 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1503,3 +1503,11 @@ namespace PR15884 {
// expected-note@-3 {{pointer to temporary is not a constant expression}}
// expected-note@-4 {{temporary created here}}
}
+
+namespace AfterError {
+ // FIXME: Suppress the 'no return statements' diagnostic if the body is invalid.
+ constexpr int error() { // expected-error {{no return statement}}
+ return foobar; // expected-error {{undeclared identifier}}
+ }
+ constexpr int k = error(); // expected-error {{must be initialized by a constant expression}}
+}
diff --git a/test/SemaCXX/constant-expression-cxx1y.cpp b/test/SemaCXX/constant-expression-cxx1y.cpp
index 824a0e8b91..ea0c9e6526 100644
--- a/test/SemaCXX/constant-expression-cxx1y.cpp
+++ b/test/SemaCXX/constant-expression-cxx1y.cpp
@@ -250,11 +250,12 @@ namespace lifetime {
}
namespace const_modify {
- constexpr int modify(int &n) { return n = 1; } // expected-note {{modification of object of const-qualified type 'const int'}}
+ constexpr int modify(int &n) { return n = 1; } // expected-note 2 {{modification of object of const-qualified type 'const int'}}
constexpr int test1() { int k = 0; return modify(k); }
- constexpr int test2() { const int k = 0; return modify(const_cast<int&>(k)); } // expected-note {{in call}}
+ constexpr int test2() { const int k = 0; return modify(const_cast<int&>(k)); } // expected-note 2 {{in call}}
static_assert(test1() == 1, "");
static_assert(test2() == 1, ""); // expected-error {{constant expression}} expected-note {{in call}}
+ constexpr int i = test2(); // expected-error {{constant expression}} expected-note {{in call}}
}
namespace null {
@@ -593,3 +594,117 @@ namespace assignment_op {
}
static_assert(testC(), "");
}
+
+namespace switch_stmt {
+ constexpr int f(char k) {
+ bool b = false;
+ int z = 6;
+ switch (k) {
+ return -1;
+ case 0:
+ if (false) {
+ case 1:
+ z = 1;
+ for (; b;) {
+ return 5;
+ while (0)
+ case 2: return 2;
+ case 7: z = 7;
+ do case 6: {
+ return z;
+ if (false)
+ case 3: return 3;
+ case 4: z = 4;
+ } while (1);
+ case 5: b = true;
+ case 9: z = 9;
+ }
+ return z;
+ } else if (false) case 8: z = 8;
+ else if (false) {
+ case 10:
+ z = -10;
+ break;
+ }
+ else z = 0;
+ return z;
+ default:
+ return -1;
+ }
+ return -z;
+ }
+ static_assert(f(0) == 0, "");
+ static_assert(f(1) == 1, "");
+ static_assert(f(2) == 2, "");
+ static_assert(f(3) == 3, "");
+ static_assert(f(4) == 4, "");
+ static_assert(f(5) == 5, "");
+ static_assert(f(6) == 6, "");
+ static_assert(f(7) == 7, "");
+ static_assert(f(8) == 8, "");
+ static_assert(f(9) == 9, "");
+ static_assert(f(10) == 10, "");
+
+ // Check that we can continue an outer loop from within a switch.
+ constexpr bool contin() {
+ for (int n = 0; n != 10; ++n) {
+ switch (n) {
+ case 0:
+ ++n;
+ continue;
+ case 1:
+ return false;
+ case 2:
+ return true;
+ }
+ }
+ return false;
+ }
+ static_assert(contin(), "");
+
+ constexpr bool switch_into_for() {
+ int n = 0;
+ switch (n) {
+ for (; n == 1; ++n) {
+ return n == 1;
+ case 0: ;
+ }
+ }
+ return false;
+ }
+ static_assert(switch_into_for(), "");
+
+ constexpr void duff_copy(char *a, const char *b, int n) {
+ switch ((n - 1) % 8 + 1) {
+ for ( ; n; n = (n - 1) & ~7) {
+ case 8: a[n-8] = b[n-8];
+ case 7: a[n-7] = b[n-7];
+ case 6: a[n-6] = b[n-6];
+ case 5: a[n-5] = b[n-5];
+ case 4: a[n-4] = b[n-4];
+ case 3: a[n-3] = b[n-3];
+ case 2: a[n-2] = b[n-2];
+ case 1: a[n-1] = b[n-1];
+ }
+ case 0: ;
+ }
+ }
+
+ constexpr bool test_copy(const char *str, int n) {
+ char buffer[16] = {};
+ duff_copy(buffer, str, n);
+ for (int i = 0; i != sizeof(buffer); ++i)
+ if (buffer[i] != (i < n ? str[i] : 0))
+ return false;
+ return true;
+ }
+ static_assert(test_copy("foo", 0), "");
+ static_assert(test_copy("foo", 1), "");
+ static_assert(test_copy("foo", 2), "");
+ static_assert(test_copy("hello world", 0), "");
+ static_assert(test_copy("hello world", 7), "");
+ static_assert(test_copy("hello world", 8), "");
+ static_assert(test_copy("hello world", 9), "");
+ static_assert(test_copy("hello world", 10), "");
+ static_assert(test_copy("hello world", 10), "");
+}
diff --git a/test/SemaCXX/enum-unscoped-nonexistent.cpp b/test/SemaCXX/enum-unscoped-nonexistent.cpp
index e9da38f558..7da9a96d60 100644
--- a/test/SemaCXX/enum-unscoped-nonexistent.cpp
+++ b/test/SemaCXX/enum-unscoped-nonexistent.cpp
@@ -6,7 +6,7 @@ struct Base {
template<typename T> struct S : Base {
enum E : int;
constexpr int f() const;
- constexpr int g() const; // expected-note {{declared here}}
+ constexpr int g() const;
void h();
};
template<> enum S<char>::E : int {}; // expected-note {{enum 'S<char>::E' was explicitly specialized here}}
@@ -23,7 +23,7 @@ static_assert(S<int>().f() == 1, "");
// The unqualified-id here names a member of the current instantiation, which
// bizarrely might not exist in some instantiations.
template<typename T> constexpr int S<T>::g() const { return b; } // expected-error {{enumerator 'b' does not exist in instantiation of 'S<char>'}}
-static_assert(S<char>().g() == 1, ""); // expected-note {{here}} expected-error {{not an integral constant expression}} expected-note {{undefined}}
+static_assert(S<char>().g() == 1, ""); // expected-note {{here}} expected-error {{not an integral constant expression}}
static_assert(S<short>().g() == 2, "");
static_assert(S<long>().g() == 8, "");
diff --git a/test/SemaCXX/ms-wchar.cpp b/test/SemaCXX/ms-wchar.cpp
index 2cbf745d33..878d8cadce 100644
--- a/test/SemaCXX/ms-wchar.cpp
+++ b/test/SemaCXX/ms-wchar.cpp
@@ -7,3 +7,6 @@ __wchar_t g = L'a';
__wchar_t s[] = L"Hello world!";
unsigned short t[] = L"Hello world!"; // expected-error{{array initializer must be an initializer list}}
+
+wchar_t u[] = 1; // expected-error{{array initializer must be an initializer list or wide string literal}}
+__wchar_t v[] = 1; // expected-error{{array initializer must be an initializer list or wide string literal}}
diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp
index 7239646d8d..228bc0ecbd 100644
--- a/test/SemaCXX/nested-name-spec.cpp
+++ b/test/SemaCXX/nested-name-spec.cpp
@@ -297,3 +297,13 @@ namespace NS {
int foobar = a + longer_b; // expected-error {{use of undeclared identifier 'a'; did you mean 'NS::a'?}} \
// expected-error {{use of undeclared identifier 'longer_b'; did you mean 'NS::longer_b'?}}
}
+
+// <rdar://problem/13853540>
+namespace N {
+ struct X { };
+ namespace N {
+ struct Foo {
+ struct N::X *foo(); // expected-error{{no struct named 'X' in namespace 'N::N'}}
+ };
+ }
+}
diff --git a/test/SemaCXX/string-init.cpp b/test/SemaCXX/string-init.cpp
new file mode 100644
index 0000000000..7e62d1855a
--- /dev/null
+++ b/test/SemaCXX/string-init.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+void f() {
+ char a1[] = "a"; // No error.
+ char a2[] = u8"a"; // No error.
+ char a3[] = u"a"; // expected-error{{initializing char array with wide string literal}}
+ char a4[] = U"a"; // expected-error{{initializing char array with wide string literal}}
+ char a5[] = L"a"; // expected-error{{initializing char array with wide string literal}}
+
+ wchar_t b1[] = "a"; // expected-error{{initializing wide char array with non-wide string literal}}
+ wchar_t b2[] = u8"a"; // expected-error{{initializing wide char array with non-wide string literal}}
+ wchar_t b3[] = u"a"; // expected-error{{initializing wide char array with incompatible wide string literal}}
+ wchar_t b4[] = U"a"; // expected-error{{initializing wide char array with incompatible wide string literal}}
+ wchar_t b5[] = L"a"; // No error.
+
+ char16_t c1[] = "a"; // expected-error{{initializing wide char array with non-wide string literal}}
+ char16_t c2[] = u8"a"; // expected-error{{initializing wide char array with non-wide string literal}}
+ char16_t c3[] = u"a"; // No error.
+ char16_t c4[] = U"a"; // expected-error{{initializing wide char array with incompatible wide string literal}}
+ char16_t c5[] = L"a"; // expected-error{{initializing wide char array with incompatible wide string literal}}
+
+ char32_t d1[] = "a"; // expected-error{{initializing wide char array with non-wide string literal}}
+ char32_t d2[] = u8"a"; // expected-error{{initializing wide char array with non-wide string literal}}
+ char32_t d3[] = u"a"; // expected-error{{initializing wide char array with incompatible wide string literal}}
+ char32_t d4[] = U"a"; // No error.
+ char32_t d5[] = L"a"; // expected-error{{initializing wide char array with incompatible wide string literal}}
+
+ int e1[] = "a"; // expected-error{{array initializer must be an initializer list}}
+ int e2[] = u8"a"; // expected-error{{array initializer must be an initializer list}}
+ int e3[] = u"a"; // expected-error{{array initializer must be an initializer list}}
+ int e4[] = U"a"; // expected-error{{array initializer must be an initializer list}}
+ int e5[] = L"a"; // expected-error{{array initializer must be an initializer list}}
+}
+
+void g() {
+ char a[] = 1; // expected-error{{array initializer must be an initializer list or string literal}}
+ wchar_t b[] = 1; // expected-error{{array initializer must be an initializer list or wide string literal}}
+ char16_t c[] = 1; // expected-error{{array initializer must be an initializer list or wide string literal}}
+ char32_t d[] = 1; // expected-error{{array initializer must be an initializer list or wide string literal}}
+}
diff --git a/test/SemaObjC/call-super-2.m b/test/SemaObjC/call-super-2.m
index 3c45a2c732..25cfbdd087 100644
--- a/test/SemaObjC/call-super-2.m
+++ b/test/SemaObjC/call-super-2.m
@@ -14,7 +14,7 @@ id objc_getClass(const char *s);
- (int) instance_func0;
@end
-@interface Derived: Object
+@interface Derived: Object // expected-note {{receiver is instance of class declared here}}
+ (int) class_func1;
+ (int) class_func2;
+ (int) class_func3;
diff --git a/test/SemaObjC/compare-qualified-id.m b/test/SemaObjC/compare-qualified-id.m
index 82868f8a16..02fa86ec8d 100644
--- a/test/SemaObjC/compare-qualified-id.m
+++ b/test/SemaObjC/compare-qualified-id.m
@@ -12,7 +12,7 @@ typedef struct _NSZone NSZone;
typedef struct {} NSFastEnumerationState;
@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; @end
@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; @end
-@interface NSMutableDictionary : NSDictionary - (void)removeObjectForKey:(id)aKey; @end
+@interface NSMutableDictionary : NSDictionary - (void)removeObjectForKey:(id)aKey; @end // expected-note {{receiver is instance of class declared here}}
extern NSString * const NSTaskDidTerminateNotification;
@interface XCPropertyExpansionContext : NSObject <NSCopying> { // expected-note {{required for direct or indirect protocol 'NSCopying'}}
diff --git a/test/SemaObjC/conditional-expr.m b/test/SemaObjC/conditional-expr.m
index ec1305dbe8..049a095ce3 100644
--- a/test/SemaObjC/conditional-expr.m
+++ b/test/SemaObjC/conditional-expr.m
@@ -33,7 +33,8 @@
@end
// No @interface declaration for DTFilterOutputStream3
-@implementation DTFilterOutputStream3 // expected-warning {{cannot find interface declaration for 'DTFilterOutputStream3'}}
+@implementation DTFilterOutputStream3 // expected-warning {{cannot find interface declaration for 'DTFilterOutputStream3'}} \
+ // expected-note {{receiver is instance of class declared here}}
- (id)initWithNextOutputStream:(id <DTOutputStreams>) outputStream {
id <DTOutputStreams> nextOutputStream = [self nextOutputStream]; // expected-warning {{method '-nextOutputStream' not found (return type defaults to 'id')}}
self = nextOutputStream; // expected-warning {{assigning to 'DTFilterOutputStream3 *' from incompatible type 'id<DTOutputStreams>'}}
diff --git a/test/SemaObjC/error-outof-scope-property-use.m b/test/SemaObjC/error-outof-scope-property-use.m
index c69a4055df..8ab9f55745 100644
--- a/test/SemaObjC/error-outof-scope-property-use.m
+++ b/test/SemaObjC/error-outof-scope-property-use.m
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -fobjc-default-synthesize-properties -verify -Wno-objc-root-class %s
// rdar://13178483
-@class NSMutableDictionary;
+@class NSMutableDictionary; // expected-note {{receiver is instance of class declared here}}
@interface LaunchdJobs
diff --git a/test/SemaObjC/instancetype.m b/test/SemaObjC/instancetype.m
index 8137964737..7811d3eba5 100644
--- a/test/SemaObjC/instancetype.m
+++ b/test/SemaObjC/instancetype.m
@@ -25,7 +25,7 @@
- (instancetype)otherMethodInProto2; // expected-note{{overridden method returns an instance of its class type}}
@end
-@interface Subclass1 : Root
+@interface Subclass1 : Root // expected-note 4 {{receiver is instance of class declared here}}
- (instancetype)initSubclass1;
- (void)methodOnSubclass1;
+ (instancetype)allocSubclass1;
diff --git a/test/SemaObjC/message.m b/test/SemaObjC/message.m
index 40fa102f35..2c4d8066f6 100644
--- a/test/SemaObjC/message.m
+++ b/test/SemaObjC/message.m
@@ -107,7 +107,7 @@ void foo5(id p) {
// expected-warning {{instance method '-bar' not found}}
}
-@interface I1
+@interface I1 // expected-note {{receiver is instance of class declared here}}
-(void)unavail_meth __attribute__((unavailable)); // expected-note {{marked unavailable here}}
@end
diff --git a/test/SemaObjC/method-not-defined.m b/test/SemaObjC/method-not-defined.m
index 22466f7dc3..792469b719 100644
--- a/test/SemaObjC/method-not-defined.m
+++ b/test/SemaObjC/method-not-defined.m
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-@interface Foo
+@interface Foo // expected-note {{receiver is instance of class declared here}}
@end
void test() {
diff --git a/test/SemaObjC/missing-atend-metadata.m b/test/SemaObjC/missing-atend-metadata.m
index f072981dc1..f235ab94d8 100644
--- a/test/SemaObjC/missing-atend-metadata.m
+++ b/test/SemaObjC/missing-atend-metadata.m
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -verify -Wno-objc-root-class %s
-@interface I0
+@interface I0 // expected-note {{receiver is instance of class declared here}}
@end
@implementation I0 // expected-note {{implementation started here}}
diff --git a/test/SemaObjC/property-5.m b/test/SemaObjC/property-5.m
index cd7cc2487a..cf4f87392b 100644
--- a/test/SemaObjC/property-5.m
+++ b/test/SemaObjC/property-5.m
@@ -8,7 +8,7 @@
@interface MutableNSData : NSData @end
-@interface Base : NSData <P1>
+@interface Base : NSData <P1> // expected-note {{receiver is instance of class declared here}}
@property(readonly) id ref;
@property(readonly) Base *p_base;
@property(readonly) NSData *nsdata;
diff --git a/test/SemaObjC/protocol-id-test-1.m b/test/SemaObjC/protocol-id-test-1.m
index 19a4432de6..36e23ed9f2 100644
--- a/test/SemaObjC/protocol-id-test-1.m
+++ b/test/SemaObjC/protocol-id-test-1.m
@@ -7,7 +7,7 @@
@protocol P
@end
-@interface INTF<P>
+@interface INTF<P> // expected-note {{receiver is instance of class declared here}}
- (void)IMeth;
@end
diff --git a/test/SemaObjCXX/instancetype.mm b/test/SemaObjCXX/instancetype.mm
index bbf100ef04..89ff2b4b03 100644
--- a/test/SemaObjCXX/instancetype.mm
+++ b/test/SemaObjCXX/instancetype.mm
@@ -25,7 +25,7 @@
- (instancetype)otherMethodInProto2; // expected-note{{overridden method returns an instance of its class type}}
@end
-@interface Subclass1 : Root
+@interface Subclass1 : Root // expected-note 4 {{receiver is instance of class declared here}}
- (instancetype)initSubclass1;
- (void)methodOnSubclass1;
+ (instancetype)allocSubclass1;
diff --git a/test/Tooling/auto-detect-from-source-parent-of-cwd.cpp b/test/Tooling/auto-detect-from-source-parent-of-cwd.cpp
index 6b632b0a0d..b1778a65e7 100644
--- a/test/Tooling/auto-detect-from-source-parent-of-cwd.cpp
+++ b/test/Tooling/auto-detect-from-source-parent-of-cwd.cpp
@@ -2,7 +2,7 @@
// RUN: mkdir -p %t/abc/def/ijk/qwe
// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -c %t/abc/def/ijk/qwe/test.cpp\",\"file\":\"%t/abc/def/ijk/qwe/test.cpp\"}]" | sed -e 's/\\/\\\\/g' > %t/compile_commands.json
// RUN: cp "%s" "%t/abc/def/ijk/qwe/test.cpp"
-// RUN: PWD="%t/abc/def" clang-check "ijk/qwe/test.cpp" 2>&1 | FileCheck %s
+// RUN: env PWD="%t/abc/def" clang-check "ijk/qwe/test.cpp" 2>&1 | FileCheck %s
// CHECK: C++ requires
invalid;
diff --git a/test/Tooling/clang-check-pwd.cpp b/test/Tooling/clang-check-pwd.cpp
index 463ed40b3e..ac245f7ec5 100644
--- a/test/Tooling/clang-check-pwd.cpp
+++ b/test/Tooling/clang-check-pwd.cpp
@@ -2,7 +2,7 @@
// RUN: mkdir %t
// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -c %t/test.cpp\",\"file\":\"%t/test.cpp\"}]" | sed -e 's/\\/\\\\/g' > %t/compile_commands.json
// RUN: cp "%s" "%t/test.cpp"
-// RUN: PWD="%t" clang-check -p "%t" "test.cpp" 2>&1|FileCheck %s
+// RUN: env PWD="%t" clang-check -p "%t" "test.cpp" 2>&1|FileCheck %s
// FIXME: Make the above easier.
// CHECK: C++ requires
diff --git a/tools/clang-format/clang-format.el b/tools/clang-format/clang-format.el
index b76eb41d94..57475ac722 100644
--- a/tools/clang-format/clang-format.el
+++ b/tools/clang-format/clang-format.el
@@ -7,25 +7,39 @@
;; (global-set-key [C-M-tab] 'clang-format-region)
;;
;; Depending on your configuration and coding style, you might need to modify
-;; 'style' and 'binary' below.
+;; 'style' in clang-format, below.
+
+;; *Location of the clang-format binary. If it is on your PATH, a full path name
+;; need not be specified.
+(defvar clang-format-binary "clang-format")
+
(defun clang-format-region ()
+ "Use clang-format to format the currently active region."
(interactive)
+ (let ((beg (if mark-active
+ (region-beginning)
+ (min (line-beginning-position) (1- (point-max)))))
+ (end (if mark-active
+ (region-end)
+ (line-end-position))))
+ (clang-format beg end)))
+
+(defun clang-format-buffer ()
+ "Use clang-format to format the current buffer."
+ (clang-format (point-min) (point-max)))
+(defun clang-format (begin end)
+ "Use clang-format to format the code between BEGIN and END."
(let* ((orig-windows (get-buffer-window-list (current-buffer)))
(orig-window-starts (mapcar #'window-start orig-windows))
(orig-point (point))
- (binary "clang-format")
(style "LLVM"))
- (if mark-active
- (setq beg (region-beginning)
- end (region-end))
- (setq beg (min (line-beginning-position) (1- (point-max)))
- end (line-end-position)))
- (call-process-region (point-min) (point-max) binary t t nil
- "-offset" (number-to-string (1- beg))
- "-length" (number-to-string (- end beg))
- "-style" style)
- (goto-char orig-point)
- (dotimes (index (length orig-windows))
- (set-window-start (nth index orig-windows)
- (nth index orig-window-starts)))))
+ (unwind-protect
+ (call-process-region (point-min) (point-max) clang-format-binary t t nil
+ "-offset" (number-to-string (1- begin))
+ "-length" (number-to-string (- end begin))
+ "-style" style)
+ (goto-char orig-point)
+ (dotimes (index (length orig-windows))
+ (set-window-start (nth index orig-windows)
+ (nth index orig-window-starts))))))
diff --git a/tools/driver/cc1as_main.cpp b/tools/driver/cc1as_main.cpp
index 232ea2f668..46ba2463f1 100644
--- a/tools/driver/cc1as_main.cpp
+++ b/tools/driver/cc1as_main.cpp
@@ -287,12 +287,12 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
// it later.
SrcMgr.setIncludeDirs(Opts.IncludePaths);
- OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(Opts.Triple));
- assert(MAI && "Unable to create target asm info!");
-
OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));
assert(MRI && "Unable to create target register info!");
+ OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, Opts.Triple));
+ assert(MAI && "Unable to create target asm info!");
+
bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
formatted_raw_ostream *Out = GetOutputStream(Opts, Diags, IsBinary);
if (!Out)
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index c25e625df5..71827f8a23 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -5681,7 +5681,7 @@ CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
const Decl *D = cxcursor::getCursorDecl(cursor);
if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
- switch (ND->getLinkage()) {
+ switch (ND->getLinkageInternal()) {
case NoLinkage: return CXLinkage_NoLinkage;
case InternalLinkage: return CXLinkage_Internal;
case UniqueExternalLinkage: return CXLinkage_UniqueExternal;
diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp
index a911ce5e95..4e47435996 100644
--- a/tools/libclang/CIndexUSRs.cpp
+++ b/tools/libclang/CIndexUSRs.cpp
@@ -151,7 +151,7 @@ bool USRGenerator::EmitDeclName(const NamedDecl *D) {
}
static inline bool ShouldGenerateLocation(const NamedDecl *D) {
- return D->getLinkage() != ExternalLinkage;
+ return !D->isExternallyVisible();
}
void USRGenerator::VisitDeclContext(const DeclContext *DC) {
@@ -309,9 +309,8 @@ void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
// Ideally we would use 'GenObjCMethod', but this is such a hot path
// for Objective-C code that we don't want to use
// DeclarationName::getAsString().
- Out << (D->isInstanceMethod() ? "(im)" : "(cm)");
- DeclarationName N(D->getSelector());
- N.printName(Out);
+ Out << (D->isInstanceMethod() ? "(im)" : "(cm)")
+ << DeclarationName(D->getSelector());
}
void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D) {
diff --git a/tools/libclang/IndexingContext.cpp b/tools/libclang/IndexingContext.cpp
index 14b430c7dc..cb9b492586 100644
--- a/tools/libclang/IndexingContext.cpp
+++ b/tools/libclang/IndexingContext.cpp
@@ -210,11 +210,12 @@ bool IndexingContext::isFunctionLocalDecl(const Decl *D) {
return false;
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
- switch (ND->getLinkage()) {
+ switch (ND->getFormalLinkage()) {
case NoLinkage:
case InternalLinkage:
return true;
case UniqueExternalLinkage:
+ llvm_unreachable("Not a sema linkage");
case ExternalLinkage:
return false;
}
diff --git a/unittests/ASTMatchers/ASTMatchersTest.h b/unittests/ASTMatchers/ASTMatchersTest.h
index 5fed85bb30..05258f7fe2 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.h
+++ b/unittests/ASTMatchers/ASTMatchersTest.h
@@ -84,6 +84,41 @@ testing::AssertionResult notMatches(const std::string &Code,
return matchesConditionally(Code, AMatcher, false, "-std=c++11");
}
+inline testing::AssertionResult
+matchesConditionallyDynamic(const std::string &Code,
+ const internal::DynTypedMatcher &AMatcher,
+ bool ExpectMatch, llvm::StringRef CompileArg) {
+ bool Found = false;
+ MatchFinder Finder;
+ Finder.addDynamicMatcher(AMatcher, new VerifyMatch(0, &Found));
+ OwningPtr<FrontendActionFactory> Factory(newFrontendActionFactory(&Finder));
+ // Some tests use typeof, which is a gnu extension.
+ std::vector<std::string> Args(1, CompileArg);
+ if (!runToolOnCodeWithArgs(Factory->create(), Code, Args)) {
+ return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";
+ }
+ if (!Found && ExpectMatch) {
+ return testing::AssertionFailure()
+ << "Could not find match in \"" << Code << "\"";
+ } else if (Found && !ExpectMatch) {
+ return testing::AssertionFailure()
+ << "Found unexpected match in \"" << Code << "\"";
+ }
+ return testing::AssertionSuccess();
+}
+
+inline testing::AssertionResult
+matchesDynamic(const std::string &Code,
+ const internal::DynTypedMatcher &AMatcher) {
+ return matchesConditionallyDynamic(Code, AMatcher, true, "-std=c++11");
+}
+
+inline testing::AssertionResult
+notMatchesDynamic(const std::string &Code,
+ const internal::DynTypedMatcher &AMatcher) {
+ return matchesConditionallyDynamic(Code, AMatcher, false, "-std=c++11");
+}
+
template <typename T>
testing::AssertionResult
matchAndVerifyResultConditionally(const std::string &Code, const T &AMatcher,
diff --git a/unittests/ASTMatchers/CMakeLists.txt b/unittests/ASTMatchers/CMakeLists.txt
index 91feaac4d9..862c6a0fd9 100644
--- a/unittests/ASTMatchers/CMakeLists.txt
+++ b/unittests/ASTMatchers/CMakeLists.txt
@@ -11,3 +11,5 @@ add_clang_unittest(ASTMatchersTests
target_link_libraries(ASTMatchersTests
gtest gtest_main clangASTMatchers clangTooling)
+
+add_subdirectory(Dynamic)
diff --git a/unittests/ASTMatchers/Dynamic/CMakeLists.txt b/unittests/ASTMatchers/Dynamic/CMakeLists.txt
new file mode 100644
index 0000000000..eb9fa549e1
--- /dev/null
+++ b/unittests/ASTMatchers/Dynamic/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_clang_unittest(DynamicASTMatchersTests
+ VariantValueTest.cpp
+ ParserTest.cpp
+ RegistryTest.cpp)
+
+target_link_libraries(DynamicASTMatchersTests
+ gtest gtest_main clangASTMatchers clangDynamicASTMatchers clangTooling)
diff --git a/unittests/ASTMatchers/Dynamic/Makefile b/unittests/ASTMatchers/Dynamic/Makefile
new file mode 100644
index 0000000000..52a02d0ec5
--- /dev/null
+++ b/unittests/ASTMatchers/Dynamic/Makefile
@@ -0,0 +1,20 @@
+##===- unittests/ASTMatchers/Dynamic/Makefile --------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL = ../../..
+
+TESTNAME = DynamicASTMatchers
+include $(CLANG_LEVEL)/../../Makefile.config
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc
+USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
+ clangRewriteCore.a clangRewriteFrontend.a clangParse.a clangSema.a \
+ clangAnalysis.a clangEdit.a clangAST.a clangASTMatchers.a \
+ clangLex.a clangBasic.a clangDynamicASTMatchers.a
+
+include $(CLANG_LEVEL)/unittests/Makefile
diff --git a/unittests/ASTMatchers/Dynamic/ParserTest.cpp b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
new file mode 100644
index 0000000000..41f522856d
--- /dev/null
+++ b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
@@ -0,0 +1,194 @@
+//===- unittest/ASTMatchers/Dynamic/ParserTest.cpp - Parser unit tests -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-------------------------------------------------------------------===//
+
+#include <string>
+#include <vector>
+
+#include "../ASTMatchersTest.h"
+#include "clang/ASTMatchers/Dynamic/Parser.h"
+#include "clang/ASTMatchers/Dynamic/Registry.h"
+#include "gtest/gtest.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+namespace {
+
+class DummyDynTypedMatcher : public DynTypedMatcher {
+public:
+ DummyDynTypedMatcher(uint64_t ID) : ID(ID) {}
+
+ typedef ast_matchers::internal::ASTMatchFinder ASTMatchFinder;
+ typedef ast_matchers::internal::BoundNodesTreeBuilder BoundNodesTreeBuilder;
+ virtual bool matches(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return false;
+ }
+
+ /// \brief Makes a copy of this matcher object.
+ virtual DynTypedMatcher *clone() const {
+ return new DummyDynTypedMatcher(ID);
+ }
+
+ /// \brief Returns a unique ID for the matcher.
+ virtual uint64_t getID() const { return ID; }
+
+private:
+ uint64_t ID;
+};
+
+class MockSema : public Parser::Sema {
+public:
+ virtual ~MockSema() {}
+
+ uint64_t expectMatcher(StringRef MatcherName) {
+ uint64_t ID = ExpectedMatchers.size() + 1;
+ ExpectedMatchers[MatcherName] = ID;
+ return ID;
+ }
+
+ void parse(StringRef Code) {
+ Diagnostics Error;
+ VariantValue Value;
+ Parser::parseExpression(Code, this, &Value, &Error);
+ Values.push_back(Value);
+ Errors.push_back(Error.ToStringFull());
+ }
+
+ DynTypedMatcher *actOnMatcherExpression(StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) {
+ MatcherInfo ToStore = { MatcherName, NameRange, Args };
+ Matchers.push_back(ToStore);
+ return new DummyDynTypedMatcher(ExpectedMatchers[MatcherName]);
+ }
+
+ struct MatcherInfo {
+ StringRef MatcherName;
+ SourceRange NameRange;
+ std::vector<ParserValue> Args;
+ };
+
+ std::vector<std::string> Errors;
+ std::vector<VariantValue> Values;
+ std::vector<MatcherInfo> Matchers;
+ llvm::StringMap<uint64_t> ExpectedMatchers;
+};
+
+TEST(ParserTest, ParseString) {
+ MockSema Sema;
+ Sema.parse("\"Foo\"");
+ Sema.parse("\"\"");
+ Sema.parse("\"Baz");
+ EXPECT_EQ(3ULL, Sema.Values.size());
+ EXPECT_EQ("Foo", Sema.Values[0].getString());
+ EXPECT_EQ("", Sema.Values[1].getString());
+ EXPECT_EQ("1:1: Error parsing string token: <\"Baz>", Sema.Errors[2]);
+}
+
+bool matchesRange(const SourceRange &Range, unsigned StartLine,
+ unsigned EndLine, unsigned StartColumn, unsigned EndColumn) {
+ EXPECT_EQ(StartLine, Range.Start.Line);
+ EXPECT_EQ(EndLine, Range.End.Line);
+ EXPECT_EQ(StartColumn, Range.Start.Column);
+ EXPECT_EQ(EndColumn, Range.End.Column);
+ return Range.Start.Line == StartLine && Range.End.Line == EndLine &&
+ Range.Start.Column == StartColumn && Range.End.Column == EndColumn;
+}
+
+TEST(ParserTest, ParseMatcher) {
+ MockSema Sema;
+ const uint64_t ExpectedFoo = Sema.expectMatcher("Foo");
+ const uint64_t ExpectedBar = Sema.expectMatcher("Bar");
+ const uint64_t ExpectedBaz = Sema.expectMatcher("Baz");
+ Sema.parse(" Foo ( Bar (), Baz( \n \"B A,Z\") ) ");
+ for (size_t i = 0, e = Sema.Errors.size(); i != e; ++i) {
+ EXPECT_EQ("", Sema.Errors[i]);
+ }
+
+ EXPECT_EQ(1ULL, Sema.Values.size());
+ EXPECT_EQ(ExpectedFoo, Sema.Values[0].getMatcher().getID());
+
+ EXPECT_EQ(3ULL, Sema.Matchers.size());
+ const MockSema::MatcherInfo Bar = Sema.Matchers[0];
+ EXPECT_EQ("Bar", Bar.MatcherName);
+ EXPECT_TRUE(matchesRange(Bar.NameRange, 1, 1, 8, 14));
+ EXPECT_EQ(0ULL, Bar.Args.size());
+
+ const MockSema::MatcherInfo Baz = Sema.Matchers[1];
+ EXPECT_EQ("Baz", Baz.MatcherName);
+ EXPECT_TRUE(matchesRange(Baz.NameRange, 1, 2, 16, 10));
+ EXPECT_EQ(1ULL, Baz.Args.size());
+ EXPECT_EQ("B A,Z", Baz.Args[0].Value.getString());
+
+ const MockSema::MatcherInfo Foo = Sema.Matchers[2];
+ EXPECT_EQ("Foo", Foo.MatcherName);
+ EXPECT_TRUE(matchesRange(Foo.NameRange, 1, 2, 2, 12));
+ EXPECT_EQ(2ULL, Foo.Args.size());
+ EXPECT_EQ(ExpectedBar, Foo.Args[0].Value.getMatcher().getID());
+ EXPECT_EQ(ExpectedBaz, Foo.Args[1].Value.getMatcher().getID());
+}
+
+using ast_matchers::internal::Matcher;
+
+TEST(ParserTest, FullParserTest) {
+ OwningPtr<DynTypedMatcher> Matcher(Parser::parseMatcherExpression(
+ "hasInitializer(binaryOperator(hasLHS(integerLiteral())))", NULL));
+ EXPECT_TRUE(matchesDynamic("int x = 1 + false;", *Matcher));
+ EXPECT_FALSE(matchesDynamic("int x = true + 1;", *Matcher));
+
+ Diagnostics Error;
+ EXPECT_TRUE(Parser::parseMatcherExpression(
+ "hasInitializer(\n binaryOperator(hasLHS(\"A\")))", &Error) == NULL);
+ EXPECT_EQ("1:1: Error parsing argument 1 for matcher hasInitializer.\n"
+ "2:5: Error parsing argument 1 for matcher binaryOperator.\n"
+ "2:20: Error building matcher hasLHS.\n"
+ "2:27: Incorrect type on function hasLHS for arg 1.",
+ Error.ToStringFull());
+}
+
+std::string ParseWithError(StringRef Code) {
+ Diagnostics Error;
+ VariantValue Value;
+ Parser::parseExpression(Code, &Value, &Error);
+ return Error.ToStringFull();
+}
+
+std::string ParseMatcherWithError(StringRef Code) {
+ Diagnostics Error;
+ Parser::parseMatcherExpression(Code, &Error);
+ return Error.ToStringFull();
+}
+
+TEST(ParserTest, Errors) {
+ EXPECT_EQ(
+ "1:5: Error parsing matcher. Found token <123> while looking for '('.",
+ ParseWithError("Foo 123"));
+ EXPECT_EQ(
+ "1:9: Error parsing matcher. Found token <123> while looking for ','.",
+ ParseWithError("Foo(\"A\" 123)"));
+ EXPECT_EQ(
+ "1:4: Error parsing matcher. Found end-of-code while looking for ')'.",
+ ParseWithError("Foo("));
+ EXPECT_EQ("1:1: End of code found while looking for token.",
+ ParseWithError(""));
+ EXPECT_EQ("Input value is not a matcher expression.",
+ ParseMatcherWithError("\"A\""));
+ EXPECT_EQ("1:1: Error parsing argument 1 for matcher Foo.\n"
+ "1:5: Invalid token <(> found when looking for a value.",
+ ParseWithError("Foo(("));
+}
+
+} // end anonymous namespace
+} // end namespace dynamic
+} // end namespace ast_matchers
+} // end namespace clang
diff --git a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
new file mode 100644
index 0000000000..64af120193
--- /dev/null
+++ b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
@@ -0,0 +1,112 @@
+//===- unittest/ASTMatchers/Dynamic/RegistryTest.cpp - Registry unit tests -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-----------------------------------------------------------------------===//
+
+#include <vector>
+
+#include "../ASTMatchersTest.h"
+#include "clang/ASTMatchers/Dynamic/Registry.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+namespace {
+
+using ast_matchers::internal::Matcher;
+
+DynTypedMatcher *constructMatcher(StringRef MatcherName, Diagnostics *Error) {
+ const std::vector<ParserValue> Args;
+ return Registry::constructMatcher(MatcherName, SourceRange(), Args, Error);
+}
+
+DynTypedMatcher *constructMatcher(StringRef MatcherName,
+ const VariantValue &Arg1,
+ Diagnostics *Error) {
+ std::vector<ParserValue> Args(1);
+ Args[0].Value = Arg1;
+ return Registry::constructMatcher(MatcherName, SourceRange(), Args, Error);
+}
+
+DynTypedMatcher *constructMatcher(StringRef MatcherName,
+ const VariantValue &Arg1,
+ const VariantValue &Arg2,
+ Diagnostics *Error) {
+ std::vector<ParserValue> Args(2);
+ Args[0].Value = Arg1;
+ Args[1].Value = Arg2;
+ return Registry::constructMatcher(MatcherName, SourceRange(), Args, Error);
+}
+
+TEST(RegistryTest, CanConstructNoArgs) {
+ OwningPtr<DynTypedMatcher> IsArrowValue(constructMatcher("isArrow", NULL));
+ OwningPtr<DynTypedMatcher> BoolValue(constructMatcher("boolLiteral", NULL));
+
+ const std::string ClassSnippet = "struct Foo { int x; };\n"
+ "Foo *foo = new Foo;\n"
+ "int i = foo->x;\n";
+ const std::string BoolSnippet = "bool Foo = true;\n";
+
+ EXPECT_TRUE(matchesDynamic(ClassSnippet, *IsArrowValue));
+ EXPECT_TRUE(matchesDynamic(BoolSnippet, *BoolValue));
+ EXPECT_FALSE(matchesDynamic(ClassSnippet, *BoolValue));
+ EXPECT_FALSE(matchesDynamic(BoolSnippet, *IsArrowValue));
+}
+
+TEST(RegistryTest, ConstructWithSimpleArgs) {
+ OwningPtr<DynTypedMatcher> Value(
+ constructMatcher("hasName", std::string("X"), NULL));
+ EXPECT_TRUE(matchesDynamic("class X {};", *Value));
+ EXPECT_FALSE(matchesDynamic("int x;", *Value));
+}
+
+TEST(RegistryTest, ConstructWithMatcherArgs) {
+ OwningPtr<DynTypedMatcher> HasInitializerSimple(
+ constructMatcher("hasInitializer", stmt(), NULL));
+ OwningPtr<DynTypedMatcher> HasInitializerComplex(
+ constructMatcher("hasInitializer", callExpr(), NULL));
+
+ std::string code = "int i;";
+ EXPECT_FALSE(matchesDynamic(code, *HasInitializerSimple));
+ EXPECT_FALSE(matchesDynamic(code, *HasInitializerComplex));
+
+ code = "int i = 1;";
+ EXPECT_TRUE(matchesDynamic(code, *HasInitializerSimple));
+ EXPECT_FALSE(matchesDynamic(code, *HasInitializerComplex));
+
+ code = "int y(); int i = y();";
+ EXPECT_TRUE(matchesDynamic(code, *HasInitializerSimple));
+ EXPECT_TRUE(matchesDynamic(code, *HasInitializerComplex));
+}
+
+TEST(RegistryTest, Errors) {
+ // Incorrect argument count.
+ OwningPtr<Diagnostics> Error(new Diagnostics());
+ EXPECT_TRUE(NULL == constructMatcher("hasInitializer", Error.get()));
+ EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
+ Error->ToString());
+ Error.reset(new Diagnostics());
+ EXPECT_TRUE(NULL == constructMatcher("isArrow", std::string(), Error.get()));
+ EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
+ Error->ToString());
+
+ // Bad argument type
+ Error.reset(new Diagnostics());
+ EXPECT_TRUE(NULL == constructMatcher("ofClass", std::string(), Error.get()));
+ EXPECT_EQ("Incorrect type on function ofClass for arg 1.", Error->ToString());
+ Error.reset(new Diagnostics());
+ EXPECT_TRUE(NULL == constructMatcher("recordDecl", recordDecl(),
+ ::std::string(), Error.get()));
+ EXPECT_EQ("Incorrect type on function recordDecl for arg 2.",
+ Error->ToString());
+}
+
+} // end anonymous namespace
+} // end namespace dynamic
+} // end namespace ast_matchers
+} // end namespace clang
diff --git a/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp b/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
new file mode 100644
index 0000000000..6c202e52fa
--- /dev/null
+++ b/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
@@ -0,0 +1,97 @@
+//===- unittest/ASTMatchers/Dynamic/VariantValueTest.cpp - VariantValue unit tests -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-----------------------------------------------------------------------------===//
+
+#include "../ASTMatchersTest.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+namespace {
+
+using ast_matchers::internal::DynTypedMatcher;
+using ast_matchers::internal::Matcher;
+
+TEST(VariantValueTest, String) {
+ const ::std::string kString = "string";
+ VariantValue Value = kString;
+
+ EXPECT_TRUE(Value.isString());
+ EXPECT_EQ(kString, Value.getString());
+
+ EXPECT_FALSE(Value.isMatcher());
+ EXPECT_FALSE(Value.isTypedMatcher<clang::Decl>());
+ EXPECT_FALSE(Value.isTypedMatcher<clang::UnaryOperator>());
+}
+
+TEST(VariantValueTest, DynTypedMatcher) {
+ VariantValue Value = stmt();
+
+ EXPECT_FALSE(Value.isString());
+
+ EXPECT_TRUE(Value.isMatcher());
+ EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());
+ EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());
+
+ // Conversion to any type of matcher works.
+ // If they are not compatible it would just return a matcher that matches
+ // nothing. We test this below.
+ Value = recordDecl();
+ EXPECT_TRUE(Value.isMatcher());
+ EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());
+ EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());
+
+ Value = unaryOperator();
+ EXPECT_TRUE(Value.isMatcher());
+ EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());
+ EXPECT_TRUE(Value.isTypedMatcher<clang::Stmt>());
+ EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());
+}
+
+TEST(VariantValueTest, Assignment) {
+ VariantValue Value = std::string("A");
+ EXPECT_TRUE(Value.isString());
+ EXPECT_EQ("A", Value.getString());
+ EXPECT_FALSE(Value.isMatcher());
+
+ Value = recordDecl();
+ EXPECT_FALSE(Value.isString());
+ EXPECT_TRUE(Value.isMatcher());
+ EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());
+ EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());
+
+ Value = VariantValue();
+ EXPECT_FALSE(Value.isString());
+ EXPECT_FALSE(Value.isMatcher());
+}
+
+TEST(GeneicValueTest, Matcher) {
+ EXPECT_TRUE(matchesDynamic(
+ "class X {};", VariantValue(recordDecl(hasName("X"))).getMatcher()));
+ EXPECT_TRUE(matchesDynamic(
+ "int x;", VariantValue(varDecl()).getTypedMatcher<clang::Decl>()));
+ EXPECT_TRUE(matchesDynamic("int foo() { return 1 + 1; }",
+ VariantValue(functionDecl()).getMatcher()));
+ // Going through the wrong Matcher<T> will fail to match, even if the
+ // underlying matcher is correct.
+ EXPECT_FALSE(matchesDynamic(
+ "int x;", VariantValue(varDecl()).getTypedMatcher<clang::Stmt>()));
+
+ EXPECT_FALSE(
+ matchesDynamic("int x;", VariantValue(functionDecl()).getMatcher()));
+ EXPECT_FALSE(matchesDynamic(
+ "int foo() { return 1 + 1; }",
+ VariantValue(declRefExpr()).getTypedMatcher<clang::DeclRefExpr>()));
+}
+
+} // end anonymous namespace
+} // end namespace dynamic
+} // end namespace ast_matchers
+} // end namespace clang
diff --git a/unittests/ASTMatchers/Makefile b/unittests/ASTMatchers/Makefile
index 2abe6eeea5..7ff42f850c 100644
--- a/unittests/ASTMatchers/Makefile
+++ b/unittests/ASTMatchers/Makefile
@@ -9,6 +9,8 @@
CLANG_LEVEL = ../..
+PARALLEL_DIRS = Dynamic
+
TESTNAME = ASTMatchers
include $(CLANG_LEVEL)/../../Makefile.config
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index f694c5b214..58dbffd863 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -32,8 +32,8 @@ protected:
CharSourceRange::getCharRange(Start, Start.getLocWithOffset(Length)));
Lexer Lex(ID, Context.Sources.getBuffer(ID), Context.Sources,
getFormattingLangOpts());
- tooling::Replacements Replace = reformat(
- Style, Lex, Context.Sources, Ranges, new IgnoringDiagConsumer());
+ tooling::Replacements Replace =
+ reformat(Style, Lex, Context.Sources, Ranges);
ReplacementCount = Replace.size();
EXPECT_TRUE(applyAllReplacements(Replace, Context.Rewrite));
DEBUG(llvm::errs() << "\n" << Context.getRewrittenText(ID) << "\n\n");
@@ -218,7 +218,7 @@ TEST_F(FormatTest, ReformatsMovedLines) {
// Tests for control statements.
//===----------------------------------------------------------------------===//
-TEST_F(FormatTest, FormatIfWithoutCompountStatement) {
+TEST_F(FormatTest, FormatIfWithoutCompoundStatement) {
verifyFormat("if (true)\n f();\ng();");
verifyFormat("if (a)\n if (b)\n if (c)\n g();\nh();");
verifyFormat("if (a)\n if (b) {\n f();\n }\ng();");
@@ -245,6 +245,10 @@ TEST_F(FormatTest, FormatIfWithoutCompountStatement) {
"}",
AllowsMergedIf);
+ EXPECT_EQ("if (a) return;", format("if(a)\nreturn;", 7, 1, AllowsMergedIf));
+ EXPECT_EQ("if (a) return; // comment",
+ format("if(a)\nreturn; // comment", 20, 1, AllowsMergedIf));
+
AllowsMergedIf.ColumnLimit = 14;
verifyFormat("if (a) return;", AllowsMergedIf);
verifyFormat("if (aaaaaaaaa)\n"
@@ -741,11 +745,11 @@ TEST_F(FormatTest, SplitsLongCxxComments) {
}
TEST_F(FormatTest, ParsesCommentsAdjacentToPPDirectives) {
- EXPECT_EQ("namespace {}\n// Test\n#define A",
+ EXPECT_EQ("namespace {\n}\n// Test\n#define A",
format("namespace {}\n // Test\n#define A"));
- EXPECT_EQ("namespace {}\n/* Test */\n#define A",
+ EXPECT_EQ("namespace {\n}\n/* Test */\n#define A",
format("namespace {}\n /* Test */\n#define A"));
- EXPECT_EQ("namespace {}\n/* Test */ #define A",
+ EXPECT_EQ("namespace {\n}\n/* Test */ #define A",
format("namespace {}\n /* Test */ #define A"));
}
@@ -1106,7 +1110,7 @@ TEST_F(FormatTest, FormatsInlineASM) {
"asm(\"movq\\t%%rbx, %%rsi\\n\\t\"\n"
" \"cpuid\\n\\t\"\n"
" \"xchgq\\t%%rbx, %%rsi\\n\\t\"\n"
- " : \"=a\" (*rEAX), \"=S\" (*rEBX), \"=c\" (*rECX), \"=d\" (*rEDX)\n"
+ " : \"=a\"(*rEAX), \"=S\"(*rEBX), \"=c\"(*rECX), \"=d\"(*rEDX)\n"
" : \"a\"(value));");
}
@@ -1642,6 +1646,14 @@ TEST_F(FormatTest, LineBreakingInBinaryExpressions) {
" SourceMgr.getSpellingColumnNumber(\n"
" TheLine.Last->FormatTok.Tok.getLocation()) -\n"
" 1);");
+
+ FormatStyle OnePerLine = getLLVMStyle();
+ OnePerLine.BinPackParameters = false;
+ verifyFormat(
+ "if (aaaaaaaaaaaaaaaaaaaaaaaaaaaa || aaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaa || aaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n}",
+ OnePerLine);
}
TEST_F(FormatTest, ExpressionIndentation) {
@@ -1761,6 +1773,33 @@ TEST_F(FormatTest, MemoizationTests) {
" aaaaa(aaaaa(aaaaa(aaaaa(aaaaa(aaaaa(aaaaa(aaaaa(aaaaa(\n"
" aaaaa())))))))))))))))))))))))))))))))))))))));",
getLLVMStyleWithColumns(65));
+ verifyFormat(
+ "aaaaa(\n"
+ " aaaaa,\n"
+ " aaaaa(\n"
+ " aaaaa,\n"
+ " aaaaa(\n"
+ " aaaaa,\n"
+ " aaaaa(\n"
+ " aaaaa,\n"
+ " aaaaa(\n"
+ " aaaaa,\n"
+ " aaaaa(\n"
+ " aaaaa,\n"
+ " aaaaa(\n"
+ " aaaaa,\n"
+ " aaaaa(\n"
+ " aaaaa,\n"
+ " aaaaa(\n"
+ " aaaaa,\n"
+ " aaaaa(\n"
+ " aaaaa,\n"
+ " aaaaa(\n"
+ " aaaaa,\n"
+ " aaaaa(\n"
+ " aaaaa,\n"
+ " aaaaa))))))))))));",
+ getLLVMStyleWithColumns(65));
// This test takes VERY long when memoization is broken.
FormatStyle OnePerLine = getLLVMStyle();
@@ -1963,7 +2002,7 @@ TEST_F(FormatTest, FormatsBuilderPattern) {
" .StartsWith(\".eh_frame\", ORDER_EH_FRAME).StartsWith(\".init\", ORDER_INIT)\n"
" .StartsWith(\".fini\", ORDER_FINI).StartsWith(\".hash\", ORDER_HASH)\n"
" .Default(ORDER_TEXT);\n");
-
+
verifyFormat("return aaaaaaaaaaaaaaaaa->aaaaa().aaaaaaaaaaaaa().aaaaaa() <\n"
" aaaaaaaaaaaaaaa->aaaaa().aaaaaaaaaaaaa().aaaaaa();");
verifyFormat(
@@ -2204,6 +2243,14 @@ TEST_F(FormatTest, AlignsStringLiterals) {
"#define LL_FORMAT \"ll\"\n"
"printf(\"aaaaa: %d, bbbbbb: %\" LL_FORMAT \"d, cccccccc: %\" LL_FORMAT\n"
" \"d, ddddddddd: %\" LL_FORMAT \"d\");");
+
+ verifyFormat("#define A(X) \\\n"
+ " \"aaaaa\" #X \"bbbbbb\" \\\n"
+ " \"ccccc\"",
+ getLLVMStyleWithColumns(23));
+ verifyFormat("#define A \"def\"\n"
+ "f(\"abc\" A \"ghi\"\n"
+ " \"jkl\");");
}
TEST_F(FormatTest, AlignsPipes) {
@@ -2638,10 +2685,16 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
verifyFormat("for (int i = a * a; i < 10; ++i) {\n}");
verifyFormat("for (int i = 0; i < a * a; ++i) {\n}");
+ verifyFormat("#define MACRO \\\n"
+ " int *i = a * b; \\\n"
+ " void f(a *b);",
+ getLLVMStyleWithColumns(19));
+
verifyIndependentOfContext("A = new SomeType *[Length];");
verifyIndependentOfContext("A = new SomeType *[Length]();");
verifyGoogleFormat("A = new SomeType* [Length]();");
verifyGoogleFormat("A = new SomeType* [Length];");
+
FormatStyle PointerLeft = getLLVMStyle();
PointerLeft.PointerBindsToType = true;
verifyFormat("delete *x;", PointerLeft);
@@ -2749,6 +2802,10 @@ TEST_F(FormatTest, FormatsFunctionTypes) {
verifyGoogleFormat("A<void*(int*, SomeType*)>;");
verifyGoogleFormat("void* (*a)(int);");
+
+ // Other constructs can look somewhat like function types:
+ verifyFormat("A<sizeof(*x)> a;");
+ verifyFormat("#define DEREF_AND_CALL_F(x) f(*x)");
}
TEST_F(FormatTest, BreaksLongDeclarations) {
@@ -2778,6 +2835,10 @@ TEST_F(FormatTest, BreaksLongDeclarations) {
" ReallyReallyLongParameterName,\n"
" const SomeType<string, SomeOtherTemplateParameter> &\n"
" AnotherLongParameterName) {}");
+ verifyFormat("template <typename A>\n"
+ "SomeLoooooooooooooooooooooongType<\n"
+ " typename some_namespace::SomeOtherType<A>::Type>\n"
+ "Function() {}");
verifyFormat(
"aaaaaaaaaaaaaaaa::aaaaaaaaaaaaaaaa<aaaaaaaaaaaaa, aaaaaaaaaaaa>\n"
" aaaaaaaaaaaaaaaaaaaaaaa;");
@@ -2860,7 +2921,10 @@ TEST_F(FormatTest, IncorrectCodeMissingSemicolon) {
" return\n"
"}",
format("void f ( ) { if ( a ) return }"));
- EXPECT_EQ("namespace N { void f() }", format("namespace N { void f() }"));
+ EXPECT_EQ("namespace N {\n"
+ "void f()\n"
+ "}",
+ format("namespace N { void f() }"));
EXPECT_EQ("namespace N {\n"
"void f() {}\n"
"void g()\n"
@@ -3016,6 +3080,13 @@ TEST_F(FormatTest, UnderstandContextOfRecordTypeKeywords) {
verifyFormat("class A::B::C {\n} n;");
// Template definitions.
+ verifyFormat(
+ "template <typename F>\n"
+ "Matcher(const Matcher<F> &Other,\n"
+ " typename enable_if_c<is_base_of<F, T>::value &&\n"
+ " !is_same<F, T>::value>::type * = 0)\n"
+ " : Implementation(new ImplicitCastMatcher<F>(Other)) {}");
+
// FIXME: This is still incorrectly handled at the formatter side.
verifyFormat("template <> struct X < 15, i < 3 && 42 < 50 && 33<28> {\n};");
@@ -3765,7 +3836,7 @@ TEST_F(FormatTest, ReformatRegionAdjustsIndent) {
"a;\n"
"}\n"
"{\n"
- " b;\n"
+ " b; //\n"
"}\n"
"}",
format("{\n"
@@ -3773,15 +3844,15 @@ TEST_F(FormatTest, ReformatRegionAdjustsIndent) {
"a;\n"
"}\n"
"{\n"
- " b;\n"
+ " b; //\n"
"}\n"
"}",
22, 2, getLLVMStyle()));
EXPECT_EQ(" {\n"
- " a;\n"
+ " a; //\n"
" }",
format(" {\n"
- "a;\n"
+ "a; //\n"
" }",
4, 2, getLLVMStyle()));
EXPECT_EQ("void f() {}\n"
@@ -3899,6 +3970,48 @@ TEST_F(FormatTest, BreakStringLiterals) {
format("#define A \"some text other\";", AlignLeft));
}
+TEST_F(FormatTest, BreakStringLiteralsBeforeUnbreakableTokenSequence) {
+ EXPECT_EQ("someFunction(\"aaabbbcccd\"\n"
+ " \"ddeeefff\");",
+ format("someFunction(\"aaabbbcccdddeeefff\");",
+ getLLVMStyleWithColumns(25)));
+ EXPECT_EQ("someFunction1234567890(\n"
+ " \"aaabbbcccdddeeefff\");",
+ format("someFunction1234567890(\"aaabbbcccdddeeefff\");",
+ getLLVMStyleWithColumns(26)));
+ EXPECT_EQ("someFunction1234567890(\n"
+ " \"aaabbbcccdddeeeff\"\n"
+ " \"f\");",
+ format("someFunction1234567890(\"aaabbbcccdddeeefff\");",
+ getLLVMStyleWithColumns(25)));
+ EXPECT_EQ("someFunction1234567890(\n"
+ " \"aaabbbcccdddeeeff\"\n"
+ " \"f\");",
+ format("someFunction1234567890(\"aaabbbcccdddeeefff\");",
+ getLLVMStyleWithColumns(24)));
+ EXPECT_EQ("someFunction(\n"
+ " \"aaabbbcc \"\n"
+ " \"dddeeefff\");",
+ format("someFunction(\"aaabbbcc dddeeefff\");",
+ getLLVMStyleWithColumns(25)));
+ EXPECT_EQ("someFunction(\"aaabbbccc \"\n"
+ " \"ddeeefff\");",
+ format("someFunction(\"aaabbbccc ddeeefff\");",
+ getLLVMStyleWithColumns(25)));
+ EXPECT_EQ("someFunction1234567890(\n"
+ " \"aaabb \"\n"
+ " \"cccdddeeefff\");",
+ format("someFunction1234567890(\"aaabb cccdddeeefff\");",
+ getLLVMStyleWithColumns(25)));
+ EXPECT_EQ("#define A \\\n"
+ " string s = \\\n"
+ " \"123456789\" \\\n"
+ " \"0\"; \\\n"
+ " int i;",
+ format("#define A string s = \"1234567890\"; int i;",
+ getLLVMStyleWithColumns(20)));
+}
+
TEST_F(FormatTest, DoNotBreakStringLiteralsInEscapeSequence) {
EXPECT_EQ("\"\\a\"",
format("\"\\a\"", getLLVMStyleWithColumns(3)));
@@ -3953,6 +4066,101 @@ TEST_F(FormatTest, DoNotCreateUnreasonableUnwrappedLines) {
"}");
}
+TEST_F(FormatTest, FormatsClosingBracesInEmptyNestedBlocks) {
+ verifyFormat("class X {\n"
+ " void f() {\n"
+ " }\n"
+ "};",
+ getLLVMStyleWithColumns(12));
+}
+
+TEST_F(FormatTest, ConfigurableIndentWidth) {
+ FormatStyle EightIndent = getLLVMStyleWithColumns(18);
+ EightIndent.IndentWidth = 8;
+ verifyFormat("void f() {\n"
+ " someFunction();\n"
+ " if (true) {\n"
+ " f();\n"
+ " }\n"
+ "}",
+ EightIndent);
+ verifyFormat("class X {\n"
+ " void f() {\n"
+ " }\n"
+ "};",
+ EightIndent);
+ verifyFormat("int x[] = {\n"
+ " call(),\n"
+ " call(),\n"
+ "};",
+ EightIndent);
+}
+
+TEST_F(FormatTest, ConfigurableUseOfTab) {
+ FormatStyle Tab = getLLVMStyleWithColumns(42);
+ Tab.IndentWidth = 8;
+ Tab.UseTab = true;
+ Tab.AlignEscapedNewlinesLeft = true;
+ verifyFormat("class X {\n"
+ "\tvoid f() {\n"
+ "\t\tsomeFunction(parameter1,\n"
+ "\t\t\t parameter2);\n"
+ "\t}\n"
+ "};",
+ Tab);
+ verifyFormat("#define A \\\n"
+ "\tvoid f() { \\\n"
+ "\t\tsomeFunction( \\\n"
+ "\t\t parameter1, \\\n"
+ "\t\t parameter2); \\\n"
+ "\t}",
+ Tab);
+}
+
+TEST_F(FormatTest, LinuxBraceBreaking) {
+ FormatStyle BreakBeforeBrace = getLLVMStyle();
+ BreakBeforeBrace.BreakBeforeBraces = FormatStyle::BS_Linux;
+ verifyFormat("namespace a\n"
+ "{\n"
+ "class A\n"
+ "{\n"
+ " void f()\n"
+ " {\n"
+ " if (true) {\n"
+ " a();\n"
+ " b();\n"
+ " }\n"
+ " }\n"
+ " void g()\n"
+ " {\n"
+ " return;\n"
+ " }\n"
+ "}\n"
+ "}",
+ BreakBeforeBrace);
+}
+
+TEST_F(FormatTest, StroustrupBraceBreaking) {
+ FormatStyle BreakBeforeBrace = getLLVMStyle();
+ BreakBeforeBrace.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
+ verifyFormat("namespace a {\n"
+ "class A {\n"
+ " void f()\n"
+ " {\n"
+ " if (true) {\n"
+ " a();\n"
+ " b();\n"
+ " }\n"
+ " }\n"
+ " void g()\n"
+ " {\n"
+ " return;\n"
+ " }\n"
+ "}\n"
+ "}",
+ BreakBeforeBrace);
+}
+
bool allStylesEqual(ArrayRef<FormatStyle> Styles) {
for (size_t i = 1; i < Styles.size(); ++i)
if (!(Styles[0] == Styles[i]))
@@ -3994,9 +4202,9 @@ TEST_F(FormatTest, ParsesConfiguration) {
#define CHECK_PARSE_BOOL(FIELD) \
Style.FIELD = false; \
EXPECT_EQ(0, parseConfiguration(#FIELD ": true", &Style).value()); \
- EXPECT_EQ(true, Style.FIELD); \
+ EXPECT_TRUE(Style.FIELD); \
EXPECT_EQ(0, parseConfiguration(#FIELD ": false", &Style).value()); \
- EXPECT_EQ(false, Style.FIELD);
+ EXPECT_FALSE(Style.FIELD);
CHECK_PARSE_BOOL(AlignEscapedNewlinesLeft);
CHECK_PARSE_BOOL(AllowAllParametersOfDeclarationOnNextLine);
@@ -4007,6 +4215,7 @@ TEST_F(FormatTest, ParsesConfiguration) {
CHECK_PARSE_BOOL(IndentCaseLabels);
CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);
CHECK_PARSE_BOOL(PointerBindsToType);
+ CHECK_PARSE_BOOL(UseTab);
CHECK_PARSE("AccessModifierOffset: -1234", AccessModifierOffset, -1234);
CHECK_PARSE("ColumnLimit: 1234", ColumnLimit, 1234u);
@@ -4016,6 +4225,7 @@ TEST_F(FormatTest, ParsesConfiguration) {
PenaltyReturnTypeOnItsOwnLine, 1234u);
CHECK_PARSE("SpacesBeforeTrailingComments: 1234",
SpacesBeforeTrailingComments, 1234u);
+ CHECK_PARSE("IndentWidth: 32", IndentWidth, 32u);
Style.Standard = FormatStyle::LS_Auto;
CHECK_PARSE("Standard: C++03", Standard, FormatStyle::LS_Cpp03);
@@ -4027,6 +4237,14 @@ TEST_F(FormatTest, ParsesConfiguration) {
CHECK_PARSE("BasedOnStyle: LLVM", ColumnLimit, BaseStyle.ColumnLimit);
CHECK_PARSE("BasedOnStyle: LLVM\nColumnLimit: 1234", ColumnLimit, 1234u);
+ Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
+ CHECK_PARSE("BreakBeforeBraces: Attach", BreakBeforeBraces,
+ FormatStyle::BS_Attach);
+ CHECK_PARSE("BreakBeforeBraces: Linux", BreakBeforeBraces,
+ FormatStyle::BS_Linux);
+ CHECK_PARSE("BreakBeforeBraces: Stroustrup", BreakBeforeBraces,
+ FormatStyle::BS_Stroustrup);
+
#undef CHECK_PARSE
#undef CHECK_PARSE_BOOL
}
diff --git a/unittests/Tooling/CompilationDatabaseTest.cpp b/unittests/Tooling/CompilationDatabaseTest.cpp
index c453b056d2..defde91b26 100644
--- a/unittests/Tooling/CompilationDatabaseTest.cpp
+++ b/unittests/Tooling/CompilationDatabaseTest.cpp
@@ -453,7 +453,7 @@ TEST(ParseFixedCompilationDatabase, ReturnsArgumentsAfterDoubleDash) {
const char *Argv[] = { "1", "2", "--\0no-constant-folding", "3", "4" };
OwningPtr<FixedCompilationDatabase> Database(
FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
- ASSERT_TRUE(Database);
+ ASSERT_TRUE(Database.isValid());
std::vector<CompileCommand> Result =
Database->getCompileCommands("source");
ASSERT_EQ(1ul, Result.size());
@@ -472,7 +472,7 @@ TEST(ParseFixedCompilationDatabase, ReturnsEmptyCommandLine) {
const char *Argv[] = { "1", "2", "--\0no-constant-folding" };
OwningPtr<FixedCompilationDatabase> Database(
FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
- ASSERT_TRUE(Database);
+ ASSERT_TRUE(Database.isValid());
std::vector<CompileCommand> Result =
Database->getCompileCommands("source");
ASSERT_EQ(1ul, Result.size());
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index eaf10a64a4..3982fc3f31 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -1094,13 +1094,13 @@ void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
" INHERITABLE_PARAM_ATTR(NAME)\n";
OS << "#endif\n\n";
- OS << "#ifndef MS_INHERITABLE_ATTR\n";
- OS << "#define MS_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
+ OS << "#ifndef MS_INHERITANCE_ATTR\n";
+ OS << "#define MS_INHERITANCE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
OS << "#endif\n\n";
- OS << "#ifndef LAST_MS_INHERITABLE_ATTR\n";
- OS << "#define LAST_MS_INHERITABLE_ATTR(NAME)"
- " MS_INHERITABLE_ATTR(NAME)\n";
+ OS << "#ifndef LAST_MS_INHERITANCE_ATTR\n";
+ OS << "#define LAST_MS_INHERITANCE_ATTR(NAME)"
+ " MS_INHERITANCE_ATTR(NAME)\n";
OS << "#endif\n\n";
Record *InhClass = Records.getClass("InheritableAttr");
@@ -1124,16 +1124,16 @@ void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
}
EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
- EmitAttrList(OS, "MS_INHERITABLE_ATTR", MSInhAttrs);
+ EmitAttrList(OS, "MS_INHERITANCE_ATTR", MSInhAttrs);
EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
EmitAttrList(OS, "ATTR", NonInhAttrs);
OS << "#undef LAST_ATTR\n";
OS << "#undef INHERITABLE_ATTR\n";
- OS << "#undef MS_INHERITABLE_ATTR\n";
+ OS << "#undef MS_INHERITANCE_ATTR\n";
OS << "#undef LAST_INHERITABLE_ATTR\n";
OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
- OS << "#undef LAST_MS_INHERITABLE_ATTR\n";
+ OS << "#undef LAST_MS_INHERITANCE_ATTR\n";
OS << "#undef ATTR\n";
}
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index 34b955e8e9..05505c99c9 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -1410,12 +1410,17 @@ static std::string GenOpString(OpKind op, const std::string &proto,
s += ", (int64x1_t)__b, 0, 1);";
break;
case OpHi:
- s += "(" + ts +
- ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 1);";
+ // nElts is for the result vector, so the source is twice that number.
+ s += "__builtin_shufflevector(__a, __a";
+ for (unsigned i = nElts; i < nElts * 2; ++i)
+ s += ", " + utostr(i);
+ s+= ");";
break;
case OpLo:
- s += "(" + ts +
- ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 0);";
+ s += "__builtin_shufflevector(__a, __a";
+ for (unsigned i = 0; i < nElts; ++i)
+ s += ", " + utostr(i);
+ s+= ");";
break;
case OpDup:
s += Duplicate(nElts, typestr, "__a") + ";";
diff --git a/www/cxx_status.html b/www/cxx_status.html
index 7643c7a7b1..a0c697f149 100644
--- a/www/cxx_status.html
+++ b/www/cxx_status.html
@@ -467,7 +467,7 @@ available.</p>
<tr>
<td>Clarifying memory allocation</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3664.html">N3664</a></td>
- <td class="full" align="center">Yes</td>
+ <td class="partial" align="center">Partial</td>
</tr>
</table>