From ee791dde723a2089c681d2ab6a9d4f96379d5f49 Mon Sep 17 00:00:00 2001
From: Roman Divacky
Date: Fri, 15 Jan 2010 15:39:40 +0000
Subject: Update clang to r93512.
---
LICENSE.TXT | 2 +-
docs/InternalsManual.html | 14 +-
docs/LanguageExtensions.html | 77 +
examples/PrintFunctionNames/README.txt | 2 +-
include/clang-c/Index.h | 57 +-
include/clang/AST/APValue.h | 31 +-
include/clang/AST/ASTContext.h | 22 +-
include/clang/AST/Attr.h | 88 +-
include/clang/AST/CharUnits.h | 28 +-
include/clang/AST/Decl.h | 2 +
include/clang/AST/DeclCXX.h | 3 +
include/clang/AST/DeclObjC.h | 14 +-
include/clang/AST/DeclarationName.h | 9 +
include/clang/AST/Expr.h | 14 +-
include/clang/AST/ExprCXX.h | 10 +-
include/clang/AST/Stmt.h | 7 +-
include/clang/AST/TypeLoc.h | 90 +-
include/clang/Analysis/PathSensitive/BugReporter.h | 7 +-
.../Analysis/PathSensitive/ConstraintManager.h | 7 +-
.../clang/Analysis/PathSensitive/GRExprEngine.h | 22 +-
include/clang/Analysis/PathSensitive/GRState.h | 44 +-
include/clang/Analysis/PathSensitive/GRSubEngine.h | 8 +-
include/clang/Analysis/PathSensitive/MemRegion.h | 65 +-
include/clang/Analysis/PathSensitive/SValuator.h | 4 +-
include/clang/Analysis/PathSensitive/Store.h | 6 +-
include/clang/Basic/Diagnostic.h | 5 +
include/clang/Basic/DiagnosticDriverKinds.td | 2 +
include/clang/Basic/DiagnosticLexKinds.td | 6 +
include/clang/Basic/DiagnosticParseKinds.td | 12 +
include/clang/Basic/DiagnosticSemaKinds.td | 120 +-
include/clang/Basic/PartialDiagnostic.h | 38 +-
include/clang/Basic/SourceLocation.h | 1 +
include/clang/Basic/TargetInfo.h | 3 +-
include/clang/Driver/CC1Options.td | 6 +-
include/clang/Driver/Options.td | 1 +
include/clang/Driver/ToolChain.h | 4 -
include/clang/Driver/Types.def | 1 +
include/clang/Frontend/CompilerInstance.h | 38 +
include/clang/Frontend/DiagnosticOptions.h | 5 +
include/clang/Frontend/PCHReader.h | 14 +-
include/clang/Frontend/Utils.h | 32 +-
include/clang/Lex/DirectoryLookup.h | 9 +-
include/clang/Lex/ExternalPreprocessorSource.h | 34 +
include/clang/Lex/HeaderMap.h | 4 +-
include/clang/Lex/HeaderSearch.h | 11 +-
include/clang/Lex/Preprocessor.h | 33 +-
include/clang/Parse/Action.h | 84 +-
include/clang/Parse/DeclSpec.h | 19 +-
include/clang/Parse/Parser.h | 11 +-
include/clang/Rewrite/Rewriter.h | 4 +-
include/clang/Sema/CodeCompleteConsumer.h | 33 +-
lib/AST/APValue.cpp | 33 +
lib/AST/ASTContext.cpp | 62 +-
lib/AST/AttrImpl.cpp | 143 ++
lib/AST/CMakeLists.txt | 1 +
lib/AST/Decl.cpp | 11 +-
lib/AST/DeclCXX.cpp | 35 +-
lib/AST/DeclarationName.cpp | 51 +-
lib/AST/Expr.cpp | 30 +-
lib/AST/ExprConstant.cpp | 108 +-
lib/AST/RecordLayoutBuilder.cpp | 11 +-
lib/AST/Stmt.cpp | 4 +-
lib/AST/StmtPrinter.cpp | 12 +-
lib/AST/TypeLoc.cpp | 12 +
lib/AST/TypePrinter.cpp | 9 +-
lib/Analysis/AnalysisContext.cpp | 4 +
lib/Analysis/BasicConstraintManager.cpp | 11 +-
lib/Analysis/BugReporter.cpp | 19 +-
lib/Analysis/CFRefCount.cpp | 25 +-
lib/Analysis/CheckSecuritySyntaxOnly.cpp | 18 +-
lib/Analysis/Environment.cpp | 7 +-
lib/Analysis/GRExprEngine.cpp | 133 +-
lib/Analysis/GRState.cpp | 3 +
lib/Analysis/MemRegion.cpp | 65 +-
lib/Analysis/OSAtomicChecker.cpp | 28 +-
lib/Analysis/RangeConstraintManager.cpp | 8 +-
lib/Analysis/RegionStore.cpp | 223 ++-
lib/Analysis/ReturnStackAddressChecker.cpp | 14 +-
lib/Analysis/SVals.cpp | 4 +
lib/Analysis/SValuator.cpp | 8 +-
lib/Analysis/SimpleConstraintManager.cpp | 47 +-
lib/Analysis/SimpleConstraintManager.h | 3 +-
lib/Analysis/SimpleSValuator.cpp | 8 +-
lib/Analysis/Store.cpp | 43 +-
lib/Basic/Diagnostic.cpp | 96 +-
lib/Basic/Targets.cpp | 456 +++--
lib/CodeGen/CGBlocks.cpp | 60 +-
lib/CodeGen/CGBlocks.h | 7 +-
lib/CodeGen/CGCXX.cpp | 671 -------
lib/CodeGen/CGClass.cpp | 394 +++-
lib/CodeGen/CGDebugInfo.cpp | 63 +-
lib/CodeGen/CGDebugInfo.h | 13 +-
lib/CodeGen/CGDecl.cpp | 2 +-
lib/CodeGen/CGDeclCXX.cpp | 36 +-
lib/CodeGen/CGExpr.cpp | 148 +-
lib/CodeGen/CGExprAgg.cpp | 3 +-
lib/CodeGen/CGExprCXX.cpp | 331 +++-
lib/CodeGen/CGExprComplex.cpp | 39 +-
lib/CodeGen/CGExprConstant.cpp | 33 +-
lib/CodeGen/CGExprScalar.cpp | 160 +-
lib/CodeGen/CGObjCGNU.cpp | 32 +-
lib/CodeGen/CGRTTI.cpp | 22 +-
lib/CodeGen/CGVtable.cpp | 259 ++-
lib/CodeGen/CGVtable.h | 110 +-
lib/CodeGen/CMakeLists.txt | 2 +-
lib/CodeGen/CodeGenFunction.cpp | 33 +-
lib/CodeGen/CodeGenFunction.h | 28 +-
lib/CodeGen/CodeGenModule.cpp | 72 +-
lib/CodeGen/CodeGenModule.h | 19 +-
lib/CodeGen/CodeGenTypes.cpp | 43 +-
lib/CodeGen/CodeGenTypes.h | 7 +-
lib/CodeGen/Mangle.cpp | 5 +-
lib/CodeGen/TargetInfo.cpp | 1904 ++++++++++++++++++++
lib/CodeGen/TargetInfo.h | 50 +
lib/Driver/ToolChains.cpp | 12 +-
lib/Driver/ToolChains.h | 2 -
lib/Driver/Tools.cpp | 19 +-
lib/Driver/Types.cpp | 2 +
lib/Frontend/ASTConsumers.cpp | 13 +
lib/Frontend/AnalysisConsumer.cpp | 12 +-
lib/Frontend/CompilerInstance.cpp | 93 +-
lib/Frontend/CompilerInvocation.cpp | 17 +-
lib/Frontend/FixItRewriter.cpp | 3 +
lib/Frontend/FrontendActions.cpp | 4 +-
lib/Frontend/InitHeaderSearch.cpp | 6 +-
lib/Frontend/InitPreprocessor.cpp | 442 ++---
lib/Frontend/PCHReader.cpp | 71 +-
lib/Frontend/PCHReaderDecl.cpp | 7 +-
lib/Frontend/PCHReaderStmt.cpp | 4 +-
lib/Frontend/PCHWriter.cpp | 16 +-
lib/Frontend/PCHWriterDecl.cpp | 4 +-
lib/Frontend/PCHWriterStmt.cpp | 1 +
lib/Frontend/PrintParserCallbacks.cpp | 3 +-
lib/Frontend/RewriteObjC.cpp | 314 +++-
lib/Frontend/TextDiagnosticPrinter.cpp | 9 +-
lib/Headers/xmmintrin.h | 2 +-
lib/Lex/HeaderMap.cpp | 27 +-
lib/Lex/HeaderSearch.cpp | 52 +-
lib/Lex/Lexer.cpp | 10 +-
lib/Lex/LiteralSupport.cpp | 9 +-
lib/Lex/PPDirectives.cpp | 79 +-
lib/Lex/PPLexerChange.cpp | 3 +-
lib/Lex/PPMacroExpansion.cpp | 72 +-
lib/Lex/Pragma.cpp | 15 +-
lib/Lex/Preprocessor.cpp | 33 +-
lib/Parse/DeclSpec.cpp | 8 +
lib/Parse/ParseDecl.cpp | 178 +-
lib/Parse/ParseDeclCXX.cpp | 58 +-
lib/Parse/ParseExpr.cpp | 24 +-
lib/Parse/ParseExprCXX.cpp | 52 +-
lib/Parse/ParseObjc.cpp | 39 +-
lib/Parse/ParseStmt.cpp | 8 +-
lib/Parse/ParseTemplate.cpp | 3 +-
lib/Parse/Parser.cpp | 6 +-
lib/Rewrite/Rewriter.cpp | 4 +-
lib/Sema/CMakeLists.txt | 1 +
lib/Sema/CodeCompleteConsumer.cpp | 51 +-
lib/Sema/IdentifierResolver.cpp | 42 -
lib/Sema/IdentifierResolver.h | 11 -
lib/Sema/Lookup.h | 31 +-
lib/Sema/Sema.cpp | 322 +---
lib/Sema/Sema.h | 116 +-
lib/Sema/SemaCXXCast.cpp | 2 +-
lib/Sema/SemaCXXScopeSpec.cpp | 26 +
lib/Sema/SemaChecking.cpp | 478 ++++-
lib/Sema/SemaCodeComplete.cpp | 1598 ++++++++++------
lib/Sema/SemaDecl.cpp | 319 +++-
lib/Sema/SemaDeclAttr.cpp | 21 +-
lib/Sema/SemaDeclCXX.cpp | 244 ++-
lib/Sema/SemaDeclObjC.cpp | 110 +-
lib/Sema/SemaExpr.cpp | 340 ++--
lib/Sema/SemaExprCXX.cpp | 279 +--
lib/Sema/SemaExprObjC.cpp | 5 +-
lib/Sema/SemaInit.cpp | 62 +-
lib/Sema/SemaLookup.cpp | 295 ++-
lib/Sema/SemaOverload.cpp | 816 ++++++---
lib/Sema/SemaOverload.h | 184 +-
lib/Sema/SemaStmt.cpp | 9 +-
lib/Sema/SemaTemplate.cpp | 54 +-
lib/Sema/SemaTemplateDeduction.cpp | 29 +-
lib/Sema/SemaTemplateInstantiate.cpp | 7 +
lib/Sema/SemaType.cpp | 63 +-
lib/Sema/TargetAttributesSema.cpp | 86 +
lib/Sema/TargetAttributesSema.h | 27 +
lib/Sema/TreeTransform.h | 64 +-
test/Analysis/CFDateGC.m | 12 +-
test/Analysis/NSString.m | 16 +
test/Analysis/PR2599.m | 2 +
test/Analysis/casts.c | 20 +
test/Analysis/dead-stores.c | 2 +
test/Analysis/misc-ps-ranges.m | 37 +
test/Analysis/misc-ps-region-store.cpp | 43 +
test/Analysis/misc-ps-region-store.m | 52 +-
test/Analysis/misc-ps.m | 38 +-
test/Analysis/rdar-6442306-1.m | 2 +
test/Analysis/reference.cpp | 11 +
test/Analysis/retain-release-basic-store.m | 2 +
test/Analysis/retain-release-region-store.m | 2 +
test/Analysis/retain-release.m | 2 +
test/Analysis/security-syntax-checks-no-emit.c | 33 +
test/Analysis/stack-addr-ps.c | 7 +
test/Analysis/uninit-vals-ps-region.c | 1 +
.../basic.lookup.qual/class.qual/p2.cpp | 27 +
.../dcl.dcl/basic.namespace/namespace.udecl/p4.cpp | 5 +-
test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp | 8 +-
test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp | 4 +-
test/CXX/special/class.ctor/p1.cpp | 42 +
.../temp.decls/temp.class/temp.static/p1-inst.cpp | 2 +-
.../temp/temp.decls/temp.class/temp.static/p1.cpp | 2 +-
test/CXX/temp/temp.decls/temp.mem/p5.cpp | 78 +
.../temp/temp.fct.spec/temp.arg.explicit/p3.cpp | 33 +
.../temp.deduct/temp.deduct.call/p3.cpp | 15 +
test/CXX/temp/temp.param/p3.cpp | 2 +-
test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp | 2 +-
test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp | 4 +-
test/CXX/temp/temp.spec/temp.explicit/p1.cpp | 4 +-
test/CodeCompletion/Inputs/macros.h | 4 +
test/CodeCompletion/enum-switch-case-qualified.cpp | 14 +-
test/CodeCompletion/enum-switch-case.c | 10 +-
test/CodeCompletion/enum-switch-case.cpp | 10 +-
test/CodeCompletion/macros.c | 30 +-
test/CodeCompletion/member-access.cpp | 22 +-
test/CodeCompletion/namespace-alias.cpp | 10 +-
test/CodeCompletion/namespace.cpp | 4 +-
test/CodeCompletion/nested-name-specifier.cpp | 6 +-
test/CodeCompletion/objc-message.m | 16 +-
test/CodeCompletion/operator.cpp | 12 +-
test/CodeCompletion/ordinary-name.c | 7 +-
test/CodeCompletion/ordinary-name.cpp | 171 ++
test/CodeCompletion/tag.c | 4 +-
test/CodeCompletion/tag.cpp | 16 +-
test/CodeCompletion/truncation.c | 10 +-
test/CodeCompletion/using-namespace.cpp | 10 +-
test/CodeCompletion/using.cpp | 12 +-
test/CodeGen/annotate.c | 8 +
test/CodeGen/complex.c | 32 +-
test/CodeGen/ext-vector.c | 11 +-
test/CodeGen/libcalls.c | 4 +-
test/CodeGen/object-size.c | 46 +-
test/CodeGenCXX/attr.cpp | 3 +
test/CodeGenCXX/condition.cpp | 28 +-
test/CodeGenCXX/constructor-template.cpp | 4 +-
test/CodeGenCXX/copy-assign-synthesis-3.cpp | 2 +
.../default-constructor-default-argument.cpp | 2 +-
test/CodeGenCXX/default-destructor-synthesis.cpp | 9 +-
test/CodeGenCXX/deferred-global-init.cpp | 16 +
test/CodeGenCXX/delete-two-arg.cpp | 2 +-
test/CodeGenCXX/dyncast.cpp | 703 ++++----
test/CodeGenCXX/eh.cpp | 46 +-
test/CodeGenCXX/expr.cpp | 4 +
test/CodeGenCXX/mangle.cpp | 7 +-
test/CodeGenCXX/member-function-pointers.cpp | 11 +
test/CodeGenCXX/reference-init.cpp | 7 +
test/CodeGenCXX/virt.cpp | 86 +-
test/CodeGenCXX/virtual-destructor-calls.cpp | 8 +-
test/CodeGenCXX/vtable-key-function.cpp | 18 +
test/CodeGenCXX/vtable-linkage.cpp | 95 +
test/Coverage/ast-printing.c | 1 +
test/Coverage/ast-printing.cpp | 2 +
test/Coverage/c-language-features.inc | 9 +
test/Driver/analyze.c | 1 -
test/Driver/clang_f_opts.c | 6 +-
test/FixIt/typo.c | 7 +-
test/FixIt/typo.cpp | 31 +-
test/FixIt/typo.m | 82 +-
test/Frontend/macros.c | 4 +
test/Index/TestClassDecl.m | 26 +-
test/Index/c-index-api-loadTU-test.m | 75 +-
test/Index/c-index-getCursor-test.m | 24 +-
test/Index/code-completion.cpp | 12 +-
test/Index/complete-at-directives.m | 51 +-
test/Index/complete-at-exprstmt.m | 22 +-
test/Index/complete-objc-message.m | 22 +-
test/Index/complete-tabs.c | 9 +
test/Lexer/has_feature_cxx0x.cpp | 101 ++
test/Lexer/hexfloat.cpp | 8 +
test/Lexer/numeric-literal-trash.c | 2 +-
test/Misc/tabstop.c | 30 +
test/Parser/cxx0x-literal-operators.cpp | 6 +-
test/Preprocessor/foo.framework/Headers/bar.h | 3 +
test/Preprocessor/foo.framework/Headers/foo.h | 6 +
test/Preprocessor/framework-include.m | 5 +
test/Preprocessor/init.c | 2 +-
test/Preprocessor/stdint.c | 22 +-
test/Rewriter/rewrite-anonymous-union.m | 30 +
test/Rewriter/rewrite-byref-vars.mm | 35 +
test/Rewriter/rewrite-eh.m | 20 +
test/Rewriter/rewrite-foreach-7.m | 7 +
test/Rewriter/rewrite-forward-class.m | 8 +
test/Rewriter/rewrite-function-decl.mm | 31 +
test/Rewriter/rewrite-ivar-use.m | 25 +
test/Rewriter/rewrite-trivial-constructor.mm | 21 +
test/Rewriter/rewrite-weak-attr.m | 13 +
test/Rewriter/weak_byref_objects.m | 15 +
test/Sema/anonymous-struct-union.c | 6 +
test/Sema/attr-noreturn.c | 2 +
test/Sema/attr-section.c | 5 +
test/Sema/block-labels.c | 2 +
test/Sema/block-misc.c | 22 +
test/Sema/block-return.c | 1 +
test/Sema/compare.c | 44 +
test/Sema/complex-int.c | 4 +
test/Sema/conditional.c | 1 +
test/Sema/conversion.c | 36 +
test/Sema/declspec.c | 2 +-
test/Sema/enum.c | 8 +
test/Sema/exprs.c | 14 +
test/Sema/format-strings.c | 1 +
test/Sema/i-c-e.c | 5 +-
test/Sema/implicit-builtin-decl.c | 3 +-
test/Sema/implicit-decl.c | 3 +-
test/Sema/invalid-decl.c | 2 +-
test/Sema/ms-fuzzy-asm.c | 1 -
test/Sema/overloadable.c | 6 +-
test/Sema/parentheses.c | 12 +-
test/Sema/self-comparison.c | 5 +
test/Sema/switch.c | 2 +-
test/Sema/unused-expr.c | 6 +-
test/Sema/var-redecl.c | 2 +-
test/Sema/warn-unreachable.c | 20 +
test/SemaCXX/aggregate-initialization.cpp | 4 +
test/SemaCXX/ambig-user-defined-conversions.cpp | 98 +-
test/SemaCXX/attr-unavailable.cpp | 4 +-
test/SemaCXX/builtin-ptrtomember-overload-1.cpp | 6 +-
test/SemaCXX/composite-pointer-type.cpp | 7 +
test/SemaCXX/condition.cpp | 4 +-
test/SemaCXX/conditional-expr.cpp | 17 +-
test/SemaCXX/constructor-initializer.cpp | 7 +-
test/SemaCXX/conversion-function.cpp | 4 +-
test/SemaCXX/converting-constructor.cpp | 2 +-
test/SemaCXX/copy-initialization.cpp | 2 +-
test/SemaCXX/dcl_init_aggr.cpp | 6 +-
test/SemaCXX/decl-init-ref.cpp | 2 +-
test/SemaCXX/default2.cpp | 4 +-
test/SemaCXX/direct-initializer.cpp | 12 +-
test/SemaCXX/functional-cast.cpp | 6 +-
test/SemaCXX/implicit-virtual-member-functions.cpp | 8 +-
test/SemaCXX/literal-operators.cpp | 43 +
test/SemaCXX/member-pointer.cpp | 14 +-
test/SemaCXX/namespace.cpp | 2 +-
test/SemaCXX/nested-name-spec.cpp | 2 +-
test/SemaCXX/overload-call.cpp | 32 +
test/SemaCXX/overload-member-call.cpp | 30 +
test/SemaCXX/overloaded-builtin-operators.cpp | 4 +-
test/SemaCXX/overloaded-operator.cpp | 39 +-
test/SemaCXX/rval-references.cpp | 6 +-
test/SemaCXX/unreachable-code.cpp | 41 +
.../virtual-member-functions-key-function.cpp | 23 +-
test/SemaCXX/warn-assignment-condition.cpp | 48 +-
test/SemaObjC/bad-receiver-1.m | 2 +
test/SemaObjC/category-1.m | 2 +-
test/SemaObjC/continuation-class-property.m | 24 +
test/SemaObjC/ivar-access-package.m | 2 +
test/SemaObjC/ivar-lookup-resolution-builtin.m | 40 +
test/SemaObjC/nonnull.m | 3 +
test/SemaObjC/property-9.m | 12 +
test/SemaObjC/protocol-archane.m | 1 +
test/SemaObjC/undef-class-messagin-error.m | 6 +-
test/SemaObjC/undef-superclass-1.m | 5 +-
test/SemaTemplate/ambiguous-ovl-print.cpp | 2 +-
test/SemaTemplate/constructor-template.cpp | 8 +-
test/SemaTemplate/default-expr-arguments.cpp | 2 +-
test/SemaTemplate/dependent-base-classes.cpp | 84 +
test/SemaTemplate/explicit-instantiation.cpp | 4 +-
test/SemaTemplate/fun-template-def.cpp | 2 +-
.../function-template-specialization.cpp | 8 +
test/SemaTemplate/injected-class-name.cpp | 6 +-
test/SemaTemplate/instantiate-expr-4.cpp | 4 +-
test/SemaTemplate/instantiate-member-class.cpp | 4 +-
test/SemaTemplate/instantiate-member-expr.cpp | 24 +
test/SemaTemplate/instantiate-static-var.cpp | 2 +-
test/SemaTemplate/instantiate-subscript.cpp | 2 +-
test/SemaTemplate/temp_class_spec.cpp | 18 +
test/SemaTemplate/typo-dependent-name.cpp | 17 +
test/SemaTemplate/virtual-member-functions.cpp | 35 +-
tools/CIndex/CIndex.cpp | 1167 +++++-------
tools/CIndex/CIndex.exports | 7 +-
tools/CIndex/CIndexCodeCompletion.cpp | 371 ++++
tools/CIndex/CIndexUSRs.cpp | 203 +++
tools/CIndex/CIndexer.cpp | 96 +
tools/CIndex/CIndexer.h | 88 +
tools/CIndex/CMakeLists.txt | 7 +-
tools/c-index-test/c-index-test.c | 125 +-
tools/driver/cc1_main.cpp | 99 +-
utils/VtableTest/Makefile | 21 +
utils/VtableTest/check-zti | 20 +
utils/VtableTest/check-ztt | 20 +
utils/VtableTest/check-zvt | 18 +
utils/VtableTest/gen.cc | 350 ++++
utils/clang-completion-mode.el | 36 +-
390 files changed, 15118 insertions(+), 6207 deletions(-)
create mode 100644 include/clang/Lex/ExternalPreprocessorSource.h
create mode 100644 lib/AST/AttrImpl.cpp
create mode 100644 lib/CodeGen/TargetInfo.cpp
create mode 100644 lib/CodeGen/TargetInfo.h
create mode 100644 lib/Sema/TargetAttributesSema.cpp
create mode 100644 lib/Sema/TargetAttributesSema.h
create mode 100644 test/Analysis/reference.cpp
create mode 100644 test/Analysis/security-syntax-checks-no-emit.c
create mode 100644 test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
create mode 100644 test/CXX/special/class.ctor/p1.cpp
create mode 100644 test/CXX/temp/temp.decls/temp.mem/p5.cpp
create mode 100644 test/CodeCompletion/Inputs/macros.h
create mode 100644 test/CodeCompletion/ordinary-name.cpp
create mode 100644 test/CodeGen/annotate.c
create mode 100644 test/CodeGenCXX/deferred-global-init.cpp
create mode 100644 test/Frontend/macros.c
create mode 100644 test/Index/complete-tabs.c
create mode 100644 test/Lexer/has_feature_cxx0x.cpp
create mode 100644 test/Lexer/hexfloat.cpp
create mode 100644 test/Misc/tabstop.c
create mode 100644 test/Preprocessor/foo.framework/Headers/bar.h
create mode 100644 test/Preprocessor/foo.framework/Headers/foo.h
create mode 100644 test/Preprocessor/framework-include.m
create mode 100644 test/Rewriter/rewrite-anonymous-union.m
create mode 100644 test/Rewriter/rewrite-byref-vars.mm
create mode 100644 test/Rewriter/rewrite-eh.m
create mode 100644 test/Rewriter/rewrite-foreach-7.m
create mode 100644 test/Rewriter/rewrite-forward-class.m
create mode 100644 test/Rewriter/rewrite-function-decl.mm
create mode 100644 test/Rewriter/rewrite-ivar-use.m
create mode 100644 test/Rewriter/rewrite-trivial-constructor.mm
create mode 100644 test/Rewriter/rewrite-weak-attr.m
create mode 100644 test/Rewriter/weak_byref_objects.m
create mode 100644 test/Sema/warn-unreachable.c
create mode 100644 test/SemaCXX/literal-operators.cpp
create mode 100644 test/SemaCXX/unreachable-code.cpp
create mode 100644 test/SemaObjC/continuation-class-property.m
create mode 100644 test/SemaObjC/ivar-lookup-resolution-builtin.m
create mode 100644 test/SemaTemplate/dependent-base-classes.cpp
create mode 100644 test/SemaTemplate/typo-dependent-name.cpp
create mode 100644 tools/CIndex/CIndexCodeCompletion.cpp
create mode 100644 tools/CIndex/CIndexUSRs.cpp
create mode 100644 tools/CIndex/CIndexer.cpp
create mode 100644 tools/CIndex/CIndexer.h
create mode 100644 utils/VtableTest/Makefile
create mode 100755 utils/VtableTest/check-zti
create mode 100755 utils/VtableTest/check-ztt
create mode 100755 utils/VtableTest/check-zvt
create mode 100644 utils/VtableTest/gen.cc
diff --git a/LICENSE.TXT b/LICENSE.TXT
index 72faf418f2879..a378a5f7fd515 100644
--- a/LICENSE.TXT
+++ b/LICENSE.TXT
@@ -4,7 +4,7 @@ LLVM Release License
University of Illinois/NCSA
Open Source License
-Copyright (c) 2007-2009 University of Illinois at Urbana-Champaign.
+Copyright (c) 2007-2010 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
diff --git a/docs/InternalsManual.html b/docs/InternalsManual.html
index f39224f47dc56..5d75eaa45390f 100644
--- a/docs/InternalsManual.html
+++ b/docs/InternalsManual.html
@@ -289,7 +289,7 @@ Clang:
Example: | "must be a %select{unary|binary|unary or binary}2
operator" |
Class: | Integers |
-Description: | This format specifier is used to merge multiple
+ |
Description: | This format specifier is used to merge multiple
related diagnostics together into one common one, without requiring the
difference to be specified as an English string argument. Instead of
specifying the string, the diagnostic gets an integer argument and the
@@ -298,7 +298,8 @@ Clang:
it is 1 it prints 'binary' if it is 2, it prints 'unary or binary'. This
allows other language translations to substitute reasonable words (or entire
phrases) based on the semantics of the diagnostic instead of having to do
- things textually. |
+ things textually.
+ The selected string does undergo formatting.
"plural" format |
Example: | "you have %1 %plural{1:mouse|:mice}1 connected to
@@ -330,6 +331,15 @@ Clang:
abort, as will a failure to match the argument against any
expression. |
+"ordinal" format |
+Example: | "ambiguity in %ordinal0 argument" |
+Class: | Integers |
+Description: | This is a formatter which represents the
+ argument number as an ordinal: the value 1 becomes 1st,
+ 3 becomes 3rd, and so on. Values less than 1
+ are not supported.
+ This formatter is currently hard-coded to use English ordinals. |
+
"objcclass" format |
Example: | "method %objcclass0 not found" |
Class: | DeclarationName |
diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html
index 414d9c89e59b8..e2a44eaed0b9e 100644
--- a/docs/LanguageExtensions.html
+++ b/docs/LanguageExtensions.html
@@ -28,6 +28,19 @@ td {
C++ exceptions
C++ RTTI
+Checks for Upcoming Standard Language Features
+
Blocks
Function Overloading in C
Builtin Functions
@@ -215,6 +228,70 @@ example, compiling code with -fexceptions enables C++ exceptions.
Use __has_feature(cxx_rtti) to determine if C++ RTTI has been enabled. For example,
compiling code with -fno-rtti disables the use of RTTI.
+
+Checks for Upcoming Standard Language Features
+
+
+The __has_feature macro can be used to query if certain upcoming
+standard language features are enabled. Those features are listed here.
+
+Currently, all features listed here are slated for inclusion in the upcoming
+C++0x standard. As a result, all the features that clang supports are enabled
+with the -std=c++0x option when compiling C++ code. Features that are
+not yet implemented will be noted.
+
+C++0x decltype()
+
+Use __has_feature(cxx_decltype) to determine if support for the
+decltype() specifier is enabled.
+
+C++0x attributes
+
+Use __has_feature(cxx_attributes) to determine if support for
+attribute parsing with C++0x's square bracket notation is enabled.
+
+
C++0x deleted functions
+
+Use __has_feature(cxx_deleted_functions) to determine if support for
+deleted function definitions (with = delete) is enabled.
+
+
C++ TR concepts
+
+Use __has_feature(cxx_lambdas) to determine if support for
+concepts is enabled. clang does not currently implement this feature.
+
+
C++0x lambdas
+
+Use __has_feature(cxx_lambdas) to determine if support for
+lambdas is enabled. clang does not currently implement this feature.
+
+
C++0x nullptr
+
+Use __has_feature(cxx_nullptr) to determine if support for
+nullptr is enabled. clang does not yet fully implement this feature.
+
+
C++0x rvalue references
+
+Use __has_feature(cxx_rvalue_references) to determine if support for
+rvalue references is enabled. clang does not yet fully implement this feature.
+
+
C++0x static_assert()
+
+Use __has_feature(cxx_static_assert) to determine if support for
+compile-time assertions using static_assert is enabled.
+
+C++0x type inference
+
+Use __has_feature(cxx_auto_type) to determine C++0x type inference
+is supported using the auto specifier. If this is disabled,
+auto will instead be a storage class specifier, as in C or C++98.
+
+C++0x variadic templates
+
+Use __has_feature(cxx_variadic_templates) to determine if support
+for templates taking any number of arguments with the ellipsis notation is
+enabled. clang does not yet fully implement this feature.
+
Blocks
diff --git a/examples/PrintFunctionNames/README.txt b/examples/PrintFunctionNames/README.txt
index ee6f7e865e910..267865c903519 100644
--- a/examples/PrintFunctionNames/README.txt
+++ b/examples/PrintFunctionNames/README.txt
@@ -6,5 +6,5 @@ TOOL_NO_EXPORT in the tools/clang Makefile).
Once the plugin is built, you can run it using:
--
-$ clang -cc1 -load path/to/PrintFunctionNames.so -plugin=print-fns some-input-file.c
+$ clang -cc1 -load path/to/PrintFunctionNames.so -plugin print-fns some-input-file.c
--
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 03b4df12596a2..f11a9eb76f43d 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -139,10 +139,14 @@ typedef struct {
enum CXCursorKind kind;
CXDecl decl;
CXStmt stmt; /* expression reference */
+ CXDecl referringDecl;
} CXCursor;
/* A unique token for looking up "visible" CXDecls from a CXTranslationUnit. */
-typedef void *CXEntity;
+typedef struct {
+ CXIndex index;
+ void *data;
+} CXEntity;
/**
* For functions returning a string that might or might not need
@@ -321,20 +325,40 @@ CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
/*
* CXEntity Operations.
*/
-CINDEX_LINKAGE const char *clang_getDeclarationName(CXEntity);
-CINDEX_LINKAGE const char *clang_getURI(CXEntity);
-CINDEX_LINKAGE CXEntity clang_getEntity(const char *URI);
+
+/* clang_getDeclaration() maps from a CXEntity to the matching CXDecl (if any)
+ * in a specified translation unit. */
+CINDEX_LINKAGE CXDecl clang_getDeclaration(CXEntity, CXTranslationUnit);
+
/*
* CXDecl Operations.
*/
CINDEX_LINKAGE CXCursor clang_getCursorFromDecl(CXDecl);
-CINDEX_LINKAGE CXEntity clang_getEntityFromDecl(CXDecl);
+CINDEX_LINKAGE CXEntity clang_getEntityFromDecl(CXIndex, CXDecl);
CINDEX_LINKAGE CXString clang_getDeclSpelling(CXDecl);
CINDEX_LINKAGE unsigned clang_getDeclLine(CXDecl);
CINDEX_LINKAGE unsigned clang_getDeclColumn(CXDecl);
+CINDEX_LINKAGE CXString clang_getDeclUSR(CXDecl);
CINDEX_LINKAGE const char *clang_getDeclSource(CXDecl); /* deprecate */
CINDEX_LINKAGE CXFile clang_getDeclSourceFile(CXDecl);
+typedef struct CXSourceLineColumn {
+ unsigned line;
+ unsigned column;
+} CXSourceLineColumn;
+
+typedef struct CXDeclExtent {
+ CXSourceLineColumn begin;
+ CXSourceLineColumn end;
+} CXSourceExtent;
+
+/* clang_getDeclExtent() returns the physical extent of a declaration. The
+ * beginning line/column pair points to the start of the first token in the
+ * declaration, and the ending line/column pair points to the last character in
+ * the last token of the declaration.
+ */
+CINDEX_LINKAGE CXSourceExtent clang_getDeclExtent(CXDecl);
+
/*
* CXCursor Operations.
*/
@@ -564,7 +588,28 @@ enum CXCompletionChunkKind {
* the text buffer. Rather, it is meant to illustrate the type that an
* expression using the given completion string would have.
*/
- CXCompletionChunk_ResultType
+ CXCompletionChunk_ResultType,
+ /**
+ * \brief A colon (':').
+ */
+ CXCompletionChunk_Colon,
+ /**
+ * \brief A semicolon (';').
+ */
+ CXCompletionChunk_SemiColon,
+ /**
+ * \brief An '=' sign.
+ */
+ CXCompletionChunk_Equal,
+ /**
+ * Horizontal space (' ').
+ */
+ CXCompletionChunk_HorizontalSpace,
+ /**
+ * Vertical space ('\n'), after which it is generally a good idea to
+ * perform indentation.
+ */
+ CXCompletionChunk_VerticalSpace
};
/**
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h
index 94d258d9e4e6d..9d4bff893f02f 100644
--- a/include/clang/AST/APValue.h
+++ b/include/clang/AST/APValue.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/APFloat.h"
namespace clang {
+ class CharUnits;
class Expr;
/// APValue - This class implements a discriminated union of [uninitialized]
@@ -47,10 +48,6 @@ private:
ComplexAPFloat() : Real(0.0), Imag(0.0) {}
};
- struct LV {
- Expr* Base;
- uint64_t Offset;
- };
struct Vec {
APValue *Elts;
unsigned NumElts;
@@ -88,9 +85,11 @@ public:
APValue(const APValue &RHS) : Kind(Uninitialized) {
*this = RHS;
}
- APValue(Expr* B, uint64_t O) : Kind(Uninitialized) {
+ APValue(Expr* B, const CharUnits &O) : Kind(Uninitialized) {
MakeLValue(); setLValue(B, O);
}
+ APValue(Expr* B);
+
~APValue() {
MakeUninit();
}
@@ -164,14 +163,8 @@ public:
return const_cast(this)->getComplexFloatImag();
}
- Expr* getLValueBase() const {
- assert(isLValue() && "Invalid accessor");
- return ((const LV*)(const void*)Data)->Base;
- }
- uint64_t getLValueOffset() const {
- assert(isLValue() && "Invalid accessor");
- return ((const LV*)(const void*)Data)->Offset;
- }
+ Expr* getLValueBase() const;
+ CharUnits getLValueOffset() const;
void setInt(const APSInt &I) {
assert(isInt() && "Invalid accessor");
@@ -202,11 +195,7 @@ public:
((ComplexAPFloat*)(char*)Data)->Real = R;
((ComplexAPFloat*)(char*)Data)->Imag = I;
}
- void setLValue(Expr *B, uint64_t O) {
- assert(isLValue() && "Invalid accessor");
- ((LV*)(char*)Data)->Base = B;
- ((LV*)(char*)Data)->Offset = O;
- }
+ void setLValue(Expr *B, const CharUnits &O);
const APValue &operator=(const APValue &RHS);
@@ -237,11 +226,7 @@ private:
new ((void*)(char*)Data) ComplexAPFloat();
Kind = ComplexFloat;
}
- void MakeLValue() {
- assert(isUninit() && "Bad state change");
- new ((void*)(char*)Data) LV();
- Kind = LValue;
- }
+ void MakeLValue();
};
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const APValue &V) {
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index bcab46d0f5ed4..5db8e20e7e482 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -699,8 +699,8 @@ public:
ObjCProtocolDecl *rProto);
/// getObjCEncodingTypeSize returns size of type for objective-c encoding
- /// purpose.
- int getObjCEncodingTypeSize(QualType t);
+ /// purpose in characters.
+ CharUnits getObjCEncodingTypeSize(QualType t);
/// This setter/getter represents the ObjC 'id' type. It is setup lazily, by
/// Sema. id is always a (typedef for a) pointer type, a pointer to a struct.
@@ -898,17 +898,18 @@ public:
return getCanonicalType(T1) == getCanonicalType(T2);
}
- /// \brief Returns this type as a completely-unqualified array type, capturing
- /// the qualifiers in Quals. This only operates on canonical types in order
- /// to ensure the ArrayType doesn't itself have qualifiers.
+ /// \brief Returns this type as a completely-unqualified array type,
+ /// capturing the qualifiers in Quals. This will remove the minimal amount of
+ /// sugaring from the types, similar to the behavior of
+ /// QualType::getUnqualifiedType().
///
- /// \param T is the canonicalized QualType, which may be an ArrayType
+ /// \param T is the qualified type, which may be an ArrayType
///
/// \param Quals will receive the full set of qualifiers that were
- /// applied to the element type of the array.
+ /// applied to the array.
///
/// \returns if this is an array type, the completely unqualified array type
- /// that corresponds to it. Otherwise, returns this->getUnqualifiedType().
+ /// that corresponds to it. Otherwise, returns T.getUnqualifiedType().
QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals);
/// \brief Determine whether the given types are equivalent after
@@ -996,7 +997,10 @@ public:
const IncompleteArrayType *getAsIncompleteArrayType(QualType T) {
return dyn_cast_or_null(getAsArrayType(T));
}
-
+ const DependentSizedArrayType *getAsDependentSizedArrayType(QualType T) {
+ return dyn_cast_or_null(getAsArrayType(T));
+ }
+
/// getBaseElementType - Returns the innermost element type of an array type.
/// For example, will return "int" for int[m][n]
QualType getBaseElementType(const ArrayType *VAT);
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 2c7ab9d67e953..03ab0f07020b3 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -55,8 +55,6 @@ public:
Cleanup,
Const,
Constructor,
- DLLExport,
- DLLImport,
Deprecated,
Destructor,
FastCall,
@@ -93,7 +91,12 @@ public:
Visibility,
WarnUnusedResult,
Weak,
- WeakImport
+ WeakImport,
+
+ FIRST_TARGET_ATTRIBUTE,
+ DLLExport,
+ DLLImport,
+ MSP430Interrupt
};
private:
@@ -158,7 +161,7 @@ public:
class ATTR##Attr : public Attr { \
public: \
ATTR##Attr() : Attr(ATTR) {} \
- virtual Attr *clone(ASTContext &C) const { return ::new (C) ATTR##Attr; }\
+ virtual Attr *clone(ASTContext &C) const; \
static bool classof(const Attr *A) { return A->getKind() == ATTR; } \
static bool classof(const ATTR##Attr *A) { return true; } \
}
@@ -174,9 +177,7 @@ public:
/// getAlignment - The specified alignment in bits.
unsigned getAlignment() const { return Alignment; }
- virtual Attr* clone(ASTContext &C) const {
- return ::new (C) PragmaPackAttr(Alignment);
- }
+ virtual Attr* clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
@@ -203,9 +204,7 @@ public:
return Alignment;
}
- virtual Attr* clone(ASTContext &C) const {
- return ::new (C) AlignedAttr(Alignment);
- }
+ virtual Attr* clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
@@ -221,7 +220,7 @@ public:
const std::string& getAnnotation() const { return Annotation; }
- virtual Attr* clone(ASTContext &C) const { return ::new (C) AnnotateAttr(Annotation); }
+ virtual Attr* clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
@@ -237,7 +236,7 @@ public:
const std::string& getLabel() const { return Label; }
- virtual Attr* clone(ASTContext &C) const { return ::new (C) AsmLabelAttr(Label); }
+ virtual Attr* clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
@@ -255,7 +254,7 @@ public:
const std::string& getAliasee() const { return Aliasee; }
- virtual Attr *clone(ASTContext &C) const { return ::new (C) AliasAttr(Aliasee); }
+ virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Alias; }
@@ -269,7 +268,7 @@ public:
int getPriority() const { return priority; }
- virtual Attr *clone(ASTContext &C) const { return ::new (C) ConstructorAttr(priority); }
+ virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Constructor; }
@@ -283,7 +282,7 @@ public:
int getPriority() const { return priority; }
- virtual Attr *clone(ASTContext &C) const { return ::new (C) DestructorAttr(priority); }
+ virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Destructor; }
@@ -294,7 +293,7 @@ class GNUInlineAttr : public Attr {
public:
GNUInlineAttr() : Attr(GNUInline) {}
- virtual Attr *clone(ASTContext &C) const { return ::new (C) GNUInlineAttr; }
+ virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
@@ -307,7 +306,7 @@ class IBOutletAttr : public Attr {
public:
IBOutletAttr() : Attr(IBOutletKind) {}
- virtual Attr *clone(ASTContext &C) const { return ::new (C) IBOutletAttr; }
+ virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
@@ -329,7 +328,7 @@ public:
const std::string& getName() const { return Name; }
- virtual Attr *clone(ASTContext &C) const { return ::new (C) SectionAttr(Name); }
+ virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
@@ -374,7 +373,7 @@ public:
return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true;
}
- virtual Attr *clone(ASTContext &C) const { return ::new (C) NonNullAttr(ArgNums, Size); }
+ virtual Attr *clone(ASTContext &C) const;
static bool classof(const Attr *A) { return A->getKind() == NonNull; }
static bool classof(const NonNullAttr *A) { return true; }
@@ -392,9 +391,7 @@ public:
int getFormatIdx() const { return formatIdx; }
int getFirstArg() const { return firstArg; }
- virtual Attr *clone(ASTContext &C) const {
- return ::new (C) FormatAttr(Type, formatIdx, firstArg);
- }
+ virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Format; }
@@ -407,9 +404,7 @@ public:
FormatArgAttr(int idx) : Attr(FormatArg), formatIdx(idx) {}
int getFormatIdx() const { return formatIdx; }
- virtual Attr *clone(ASTContext &C) const {
- return ::new (C) FormatArgAttr(formatIdx);
- }
+ virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == FormatArg; }
@@ -424,9 +419,7 @@ public:
int getSentinel() const { return sentinel; }
int getNullPos() const { return NullPos; }
- virtual Attr *clone(ASTContext &C) const {
- return ::new (C) SentinelAttr(sentinel, NullPos);
- }
+ virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Sentinel; }
@@ -449,15 +442,13 @@ public:
VisibilityTypes getVisibility() const { return VisibilityType; }
- virtual Attr *clone(ASTContext &C) const { return ::new (C) VisibilityAttr(VisibilityType); }
+ virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Visibility; }
static bool classof(const VisibilityAttr *A) { return true; }
};
-DEF_SIMPLE_ATTR(DLLImport);
-DEF_SIMPLE_ATTR(DLLExport);
DEF_SIMPLE_ATTR(FastCall);
DEF_SIMPLE_ATTR(StdCall);
DEF_SIMPLE_ATTR(CDecl);
@@ -471,9 +462,7 @@ public:
virtual bool isMerged() const { return false; }
- virtual Attr *clone(ASTContext &C) const {
- return ::new (C) OverloadableAttr;
- }
+ virtual Attr *clone(ASTContext &C) const;
static bool classof(const Attr *A) { return A->getKind() == Overloadable; }
static bool classof(const OverloadableAttr *) { return true; }
@@ -491,7 +480,7 @@ public:
BlocksAttrTypes getType() const { return BlocksAttrType; }
- virtual Attr *clone(ASTContext &C) const { return ::new (C) BlocksAttr(BlocksAttrType); }
+ virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Blocks; }
@@ -508,7 +497,7 @@ public:
const FunctionDecl *getFunctionDecl() const { return FD; }
- virtual Attr *clone(ASTContext &C) const { return ::new (C) CleanupAttr(FD); }
+ virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Cleanup; }
@@ -527,9 +516,7 @@ public:
unsigned getNumParams() const { return NumParams; }
- virtual Attr *clone(ASTContext &C) const {
- return ::new (C) RegparmAttr(NumParams);
- }
+ virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Regparm; }
@@ -546,9 +533,7 @@ public:
unsigned getYDim() const { return Y; }
unsigned getZDim() const { return Z; }
- virtual Attr *clone(ASTContext &C) const {
- return ::new (C) ReqdWorkGroupSizeAttr(X, Y, Z);
- }
+ virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
@@ -566,6 +551,25 @@ DEF_SIMPLE_ATTR(BaseCheck);
DEF_SIMPLE_ATTR(Hiding);
DEF_SIMPLE_ATTR(Override);
+// Target-specific attributes
+DEF_SIMPLE_ATTR(DLLImport);
+DEF_SIMPLE_ATTR(DLLExport);
+
+class MSP430InterruptAttr : public Attr {
+ unsigned Number;
+
+public:
+ MSP430InterruptAttr(unsigned n) : Attr(MSP430Interrupt), Number(n) {}
+
+ unsigned getNumber() const { return Number; }
+
+ virtual Attr *clone(ASTContext &C) const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) { return A->getKind() == MSP430Interrupt; }
+ static bool classof(const MSP430InterruptAttr *A) { return true; }
+};
+
#undef DEF_SIMPLE_ATTR
} // end namespace clang
diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h
index 7b2833c53ffa5..0bb4b769d0f35 100644
--- a/include/clang/AST/CharUnits.h
+++ b/include/clang/AST/CharUnits.h
@@ -36,12 +36,12 @@ namespace clang {
/// in character units.
class CharUnits {
public:
- typedef int64_t RawType;
+ typedef int64_t QuantityType;
private:
- RawType Quantity;
+ QuantityType Quantity;
- explicit CharUnits(RawType C) : Quantity(C) {}
+ explicit CharUnits(QuantityType C) : Quantity(C) {}
public:
@@ -58,8 +58,8 @@ namespace clang {
return CharUnits(1);
}
- /// fromRaw - Construct a CharUnits quantity from a raw integer type.
- static CharUnits fromRaw(RawType Quantity) {
+ /// fromQuantity - Construct a CharUnits quantity from a raw integer type.
+ static CharUnits fromQuantity(QuantityType Quantity) {
return CharUnits(Quantity);
}
@@ -103,26 +103,26 @@ namespace clang {
/// isOne - Test whether the quantity equals one.
bool isOne() const { return Quantity == 1; }
- /// isPositive - Test whether the quanity is greater than zero.
+ /// isPositive - Test whether the quantity is greater than zero.
bool isPositive() const { return Quantity > 0; }
/// isNegative - Test whether the quantity is less than zero.
bool isNegative() const { return Quantity < 0; }
// Arithmetic operators.
- CharUnits operator* (RawType N) const {
+ CharUnits operator* (QuantityType N) const {
return CharUnits(Quantity * N);
}
- CharUnits operator/ (RawType N) const {
+ CharUnits operator/ (QuantityType N) const {
return CharUnits(Quantity / N);
}
- RawType operator/ (const CharUnits &Other) const {
+ QuantityType operator/ (const CharUnits &Other) const {
return Quantity / Other.Quantity;
}
- CharUnits operator% (RawType N) const {
+ CharUnits operator% (QuantityType N) const {
return CharUnits(Quantity % N);
}
- RawType operator% (const CharUnits &Other) const {
+ QuantityType operator% (const CharUnits &Other) const {
return Quantity % Other.Quantity;
}
CharUnits operator+ (const CharUnits &Other) const {
@@ -134,14 +134,14 @@ namespace clang {
// Conversions.
- /// getRaw - Get the raw integer representation of this quantity.
- RawType getRaw() const { return Quantity; }
+ /// getQuantity - Get the raw integer representation of this quantity.
+ QuantityType getQuantity() const { return Quantity; }
}; // class CharUnit
} // namespace clang
-inline clang::CharUnits operator* (clang::CharUnits::RawType Scale,
+inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
const clang::CharUnits &CU) {
return CU * Scale;
}
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index d0d94aafb8d04..21b59099138a8 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -1184,6 +1184,8 @@ public:
OverloadedOperatorKind getOverloadedOperator() const;
+ const IdentifierInfo *getLiteralIdentifier() const;
+
/// \brief If this function is an instantiation of a member function
/// of a class template specialization, retrieves the function from
/// which it was instantiated.
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 02581c1241a4c..336a895de8cfb 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -393,6 +393,9 @@ public:
return reverse_base_class_const_iterator(vbases_begin());
}
+ /// \brief Determine whether this class has any dependent base classes.
+ bool hasAnyDependentBases() const;
+
/// Iterator access to method members. The method iterator visits
/// all method members of the class, including non-instance methods,
/// special methods, etc.
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index ba17eb1c1d605..920d31fc7ce40 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -289,7 +289,9 @@ struct ObjCMethodList {
/// ObjCProtocolDecl, and ObjCImplDecl.
///
class ObjCContainerDecl : public NamedDecl, public DeclContext {
- SourceLocation AtEndLoc; // marks the end of the method container.
+ // These two locations in the range mark the end of the method container.
+ // The first points to the '@' token, and the second to the 'end' token.
+ SourceRange AtEnd;
public:
ObjCContainerDecl(Kind DK, DeclContext *DC, SourceLocation L,
@@ -351,11 +353,15 @@ public:
IdentifierInfo *PropertyId) const;
// Marks the end of the container.
- SourceLocation getAtEndLoc() const { return AtEndLoc; }
- void setAtEndLoc(SourceLocation L) { AtEndLoc = L; }
+ SourceRange getAtEndRange() const {
+ return AtEnd;
+ }
+ void setAtEndRange(SourceRange atEnd) {
+ AtEnd = atEnd;
+ }
virtual SourceRange getSourceRange() const {
- return SourceRange(getLocation(), getAtEndLoc());
+ return SourceRange(getLocation(), getAtEndRange().getEnd());
}
// Implement isa/cast/dyncast/etc.
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index fcb4ae52e7eb4..59d7e439e570a 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -190,6 +190,14 @@ public:
/// getNameKind - Determine what kind of name this is.
NameKind getNameKind() const;
+ /// \brief Determines whether the name itself is dependent, e.g., because it
+ /// involves a C++ type that is itself dependent.
+ ///
+ /// Note that this does not capture all of the notions of "dependent name",
+ /// because an identifier can be a dependent name if it is used as the
+ /// callee in a call expression with dependent arguments.
+ bool isDependentName() const;
+
/// getName - Retrieve the human-readable string for this name.
std::string getAsString() const;
@@ -301,6 +309,7 @@ inline bool operator>=(DeclarationName LHS, DeclarationName RHS) {
class DeclarationNameTable {
void *CXXSpecialNamesImpl; // Actually a FoldingSet *
CXXOperatorIdName *CXXOperatorNames; // Operator names
+ void *CXXLiteralOperatorNames; // Actually a FoldingSet<...> *
DeclarationNameTable(const DeclarationNameTable&); // NONCOPYABLE
DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 0cb22df92ff75..cfbae9fb2cbf5 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -241,6 +241,11 @@ public:
/// stack based objects.
bool EvaluateAsAny(EvalResult &Result, ASTContext &Ctx) const;
+ /// EvaluateAsBooleanCondition - Return true if this is a constant
+ /// which we we can fold and convert to a boolean condition using
+ /// any crazy technique that we want to.
+ bool EvaluateAsBooleanCondition(bool &Result, ASTContext &Ctx) const;
+
/// isEvaluatable - Call Evaluate to see if this expression can be constant
/// folded, but discard the result.
bool isEvaluatable(ASTContext &Ctx) const;
@@ -2552,7 +2557,7 @@ private:
unsigned NumSubExprs : 16;
- DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
+ DesignatedInitExpr(ASTContext &C, QualType Ty, unsigned NumDesignators,
const Designator *Designators,
SourceLocation EqualOrColonLoc, bool GNUSyntax,
Expr **IndexExprs, unsigned NumIndexExprs,
@@ -2565,6 +2570,8 @@ private:
protected:
virtual void DoDestroy(ASTContext &C);
+ void DestroyDesignators(ASTContext &C);
+
public:
/// A field designator, e.g., ".x".
struct FieldDesignator {
@@ -2732,7 +2739,8 @@ public:
Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; }
- void setDesignators(const Designator *Desigs, unsigned NumDesigs);
+ void setDesignators(ASTContext &C, const Designator *Desigs,
+ unsigned NumDesigs);
Expr *getArrayIndex(const Designator& D);
Expr *getArrayRangeStart(const Designator& D);
@@ -2779,7 +2787,7 @@ public:
/// \brief Replaces the designator at index @p Idx with the series
/// of designators in [First, Last).
- void ExpandDesignator(unsigned Idx, const Designator *First,
+ void ExpandDesignator(ASTContext &C, unsigned Idx, const Designator *First,
const Designator *Last);
virtual SourceRange getSourceRange() const;
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index d0e21f576d75e..55d5108e6174a 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -324,17 +324,21 @@ public:
/// @endcode
class CXXThisExpr : public Expr {
SourceLocation Loc;
-
+ bool Implicit : 1;
+
public:
- CXXThisExpr(SourceLocation L, QualType Type)
+ CXXThisExpr(SourceLocation L, QualType Type, bool isImplicit)
: Expr(CXXThisExprClass, Type,
// 'this' is type-dependent if the class type of the enclosing
// member function is dependent (C++ [temp.dep.expr]p2)
Type->isDependentType(), Type->isDependentType()),
- Loc(L) { }
+ Loc(L), Implicit(isImplicit) { }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ bool isImplicit() const { return Implicit; }
+ void setImplicit(bool I) { Implicit = I; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXThisExprClass;
}
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 33edadc3a5e64..d058f838a0084 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -1116,6 +1116,7 @@ class AsmStmt : public Stmt {
bool IsSimple;
bool IsVolatile;
+ bool MSAsm;
unsigned NumOutputs;
unsigned NumInputs;
@@ -1126,7 +1127,7 @@ class AsmStmt : public Stmt {
llvm::SmallVector Clobbers;
public:
- AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile,
+ AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile, bool msasm,
unsigned numoutputs, unsigned numinputs,
std::string *names, StringLiteral **constraints,
Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
@@ -1143,7 +1144,9 @@ public:
bool isVolatile() const { return IsVolatile; }
void setVolatile(bool V) { IsVolatile = V; }
bool isSimple() const { return IsSimple; }
- void setSimple(bool V) { IsSimple = false; }
+ void setSimple(bool V) { IsSimple = V; }
+ bool isMSAsm() const { return MSAsm; }
+ void setMSAsm(bool V) { MSAsm = V; }
//===--- Asm String Analysis ---===//
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 3e74d07ff7f34..c36c0ffde32ed 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -1029,18 +1029,88 @@ class ComplexTypeLoc : public InheritingConcreteTypeLoc {
};
-// FIXME: location of the 'typeof' and parens (the expression is
-// carried by the type).
-class TypeOfExprTypeLoc : public InheritingConcreteTypeLoc {
+struct TypeofLocInfo {
+ SourceLocation TypeofLoc;
+ SourceLocation LParenLoc;
+ SourceLocation RParenLoc;
};
-// FIXME: location of the 'typeof' and parens; also the TypeSourceInfo
-// for the inner type, or (maybe) just express that inline to the TypeLoc.
-class TypeOfTypeLoc : public InheritingConcreteTypeLoc {
+struct TypeOfExprTypeLocInfo : public TypeofLocInfo {
+};
+
+struct TypeOfTypeLocInfo : public TypeofLocInfo {
+ TypeSourceInfo* UnderlyingTInfo;
+};
+
+template
+class TypeofLikeTypeLoc
+ : public ConcreteTypeLoc {
+public:
+ SourceLocation getTypeofLoc() const {
+ return this->getLocalData()->TypeofLoc;
+ }
+ void setTypeofLoc(SourceLocation Loc) {
+ this->getLocalData()->TypeofLoc = Loc;
+ }
+
+ SourceLocation getLParenLoc() const {
+ return this->getLocalData()->LParenLoc;
+ }
+ void setLParenLoc(SourceLocation Loc) {
+ this->getLocalData()->LParenLoc = Loc;
+ }
+
+ SourceLocation getRParenLoc() const {
+ return this->getLocalData()->RParenLoc;
+ }
+ void setRParenLoc(SourceLocation Loc) {
+ this->getLocalData()->RParenLoc = Loc;
+ }
+
+ SourceRange getParensRange() const {
+ return SourceRange(getLParenLoc(), getRParenLoc());
+ }
+ void setParensRange(SourceRange range) {
+ setLParenLoc(range.getBegin());
+ setRParenLoc(range.getEnd());
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getTypeofLoc(), getRParenLoc());
+ }
+
+ void initializeLocal(SourceLocation Loc) {
+ setTypeofLoc(Loc);
+ setLParenLoc(Loc);
+ setRParenLoc(Loc);
+ }
+};
+
+class TypeOfExprTypeLoc : public TypeofLikeTypeLoc {
+public:
+ Expr* getUnderlyingExpr() const {
+ return getTypePtr()->getUnderlyingExpr();
+ }
+ // Reimplemented to account for GNU/C++ extension
+ // typeof unary-expression
+ // where there are no parentheses.
+ SourceRange getSourceRange() const;
+};
+
+class TypeOfTypeLoc
+ : public TypeofLikeTypeLoc {
+public:
+ QualType getUnderlyingType() const {
+ return this->getTypePtr()->getUnderlyingType();
+ }
+ TypeSourceInfo* getUnderlyingTInfo() const {
+ return this->getLocalData()->UnderlyingTInfo;
+ }
+ void setUnderlyingTInfo(TypeSourceInfo* TI) const {
+ this->getLocalData()->UnderlyingTInfo = TI;
+ }
};
// FIXME: location of the 'decltype' and parens.
diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h
index ccebf01b76afb..6f6681a3629be 100644
--- a/include/clang/Analysis/PathSensitive/BugReporter.h
+++ b/include/clang/Analysis/PathSensitive/BugReporter.h
@@ -23,7 +23,6 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/ImmutableSet.h"
#include
@@ -104,9 +103,9 @@ public:
// BugReporter.
const Stmt* getStmt() const;
- const std::string& getDescription() const { return Description; }
+ const llvm::StringRef getDescription() const { return Description; }
- const std::string& getShortDescription() const {
+ const llvm::StringRef getShortDescription() const {
return ShortDescription.empty() ? Description : ShortDescription;
}
@@ -444,7 +443,7 @@ public:
// FIXME: Move out-of-line (virtual function).
SourceLocation getLocation() const { return L; }
- void addString(const std::string& s) { Strs.push_back(s); }
+ void addString(llvm::StringRef s) { Strs.push_back(s); }
typedef std::list::const_iterator str_iterator;
str_iterator str_begin() const { return Strs.begin(); }
diff --git a/include/clang/Analysis/PathSensitive/ConstraintManager.h b/include/clang/Analysis/PathSensitive/ConstraintManager.h
index 37a14083ac558..c8292802ae9d9 100644
--- a/include/clang/Analysis/PathSensitive/ConstraintManager.h
+++ b/include/clang/Analysis/PathSensitive/ConstraintManager.h
@@ -25,6 +25,7 @@ namespace clang {
class GRState;
class GRStateManager;
+class GRSubEngine;
class SVal;
class ConstraintManager {
@@ -64,8 +65,10 @@ public:
virtual bool canReasonAbout(SVal X) const = 0;
};
-ConstraintManager* CreateBasicConstraintManager(GRStateManager& statemgr);
-ConstraintManager* CreateRangeConstraintManager(GRStateManager& statemgr);
+ConstraintManager* CreateBasicConstraintManager(GRStateManager& statemgr,
+ GRSubEngine &subengine);
+ConstraintManager* CreateRangeConstraintManager(GRStateManager& statemgr,
+ GRSubEngine &subengine);
} // end clang namespace
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
index e05c6243846da..fb0e88301fd68 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -87,9 +87,11 @@ class GRExprEngine : public GRSubEngine {
// this object be placed at the very end of member variables so that its
// destructor is called before the rest of the GRExprEngine is destroyed.
GRBugReporter BR;
+
+ llvm::OwningPtr TF;
public:
- GRExprEngine(AnalysisManager &mgr);
+ GRExprEngine(AnalysisManager &mgr, GRTransferFuncs *tf);
~GRExprEngine();
@@ -104,18 +106,14 @@ public:
SValuator &getSValuator() { return SVator; }
- GRTransferFuncs& getTF() { return *StateMgr.TF; }
+ GRTransferFuncs& getTF() { return *TF; }
BugReporter& getBugReporter() { return BR; }
GRStmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; }
- /// setTransferFunctions
- void setTransferFunctionsAndCheckers(GRTransferFuncs* tf);
-
- void setTransferFunctions(GRTransferFuncs& tf) {
- setTransferFunctionsAndCheckers(&tf);
- }
+ // FIXME: Remove once GRTransferFuncs is no longer referenced.
+ void setTransferFunction(GRTransferFuncs* tf);
/// ViewGraph - Visualize the ExplodedGraph created by executing the
/// simulation.
@@ -173,6 +171,10 @@ public:
/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
void ProcessEndPath(GREndPathNodeBuilder& builder);
+
+ /// EvalAssume - Callback function invoked by the ConstraintManager when
+ /// making assumptions about state values.
+ const GRState *ProcessAssume(const GRState *state, SVal cond, bool assumption);
GRStateManager& getStateManager() { return StateMgr; }
const GRStateManager& getStateManager() const { return StateMgr; }
@@ -351,6 +353,10 @@ protected:
void VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet & Dst);
+ /// Create a C++ temporary object for an rvalue.
+ void CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
/// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
/// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
/// with those assumptions.
diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h
index 424b0d77e84c0..11cdac0e96de6 100644
--- a/include/clang/Analysis/PathSensitive/GRState.h
+++ b/include/clang/Analysis/PathSensitive/GRState.h
@@ -40,10 +40,10 @@
namespace clang {
class GRStateManager;
-class GRTransferFuncs;
class Checker;
-typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&);
+typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&,
+ GRSubEngine&);
typedef StoreManager* (*StoreManagerCreator)(GRStateManager&);
//===----------------------------------------------------------------------===//
@@ -159,10 +159,6 @@ public:
BasicValueFactory &getBasicVals() const;
SymbolManager &getSymbolManager() const;
- GRTransferFuncs &getTransferFuncs() const;
-
- std::vector >::iterator checker_begin() const;
- std::vector >::iterator checker_end() const;
//==---------------------------------------------------------------------==//
// Constraints on values.
@@ -391,9 +387,8 @@ public:
//===----------------------------------------------------------------------===//
class GRStateManager {
- friend class GRExprEngine;
friend class GRState;
-
+ friend class GRExprEngine; // FIXME: Remove.
private:
EnvironmentManager EnvMgr;
llvm::OwningPtr StoreMgr;
@@ -416,27 +411,20 @@ private:
ValueManager ValueMgr;
/// Alloc - A BumpPtrAllocator to allocate states.
- llvm::BumpPtrAllocator& Alloc;
-
- /// TF - Object that represents a bundle of transfer functions
- /// for manipulating and creating SVals.
- GRTransferFuncs* TF;
-
- /// Reference to all checkers in GRExprEngine.
- std::vector > *Checkers;
+ llvm::BumpPtrAllocator &Alloc;
public:
-
GRStateManager(ASTContext& Ctx,
StoreManagerCreator CreateStoreManager,
ConstraintManagerCreator CreateConstraintManager,
- llvm::BumpPtrAllocator& alloc)
+ llvm::BumpPtrAllocator& alloc,
+ GRSubEngine &subeng)
: EnvMgr(alloc),
GDMFactory(alloc),
ValueMgr(alloc, Ctx, *this),
Alloc(alloc) {
StoreMgr.reset((*CreateStoreManager)(*this));
- ConstraintMgr.reset((*CreateConstraintManager)(*this));
+ ConstraintMgr.reset((*CreateConstraintManager)(*this, subeng));
}
~GRStateManager();
@@ -446,10 +434,6 @@ public:
ASTContext &getContext() { return ValueMgr.getContext(); }
const ASTContext &getContext() const { return ValueMgr.getContext(); }
- GRTransferFuncs& getTransferFuncs() { return *TF; }
-
- std::vector > &getCheckers() { return *Checkers;}
-
BasicValueFactory &getBasicVals() {
return ValueMgr.getBasicValueFactory();
}
@@ -702,20 +686,6 @@ inline SymbolManager &GRState::getSymbolManager() const {
return getStateManager().getSymbolManager();
}
-inline GRTransferFuncs &GRState::getTransferFuncs() const {
- return getStateManager().getTransferFuncs();
-}
-
-inline std::vector >::iterator
-GRState::checker_begin() const {
- return getStateManager().getCheckers().begin();
-}
-
-inline std::vector >::iterator
-GRState::checker_end() const {
- return getStateManager().getCheckers().end();
-}
-
template
const GRState *GRState::add(typename GRStateTrait::key_type K) const {
return getStateManager().add(this, K, get_context());
diff --git a/include/clang/Analysis/PathSensitive/GRSubEngine.h b/include/clang/Analysis/PathSensitive/GRSubEngine.h
index 330742d8bf990..5b383fae9bd08 100644
--- a/include/clang/Analysis/PathSensitive/GRSubEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRSubEngine.h
@@ -13,6 +13,8 @@
#ifndef LLVM_CLANG_ANALYSIS_GRSUBENGINE_H
#define LLVM_CLANG_ANALYSIS_GRSUBENGINE_H
+#include "clang/Analysis/PathSensitive/SVals.h"
+
namespace clang {
class Stmt;
@@ -62,8 +64,12 @@ public:
/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
virtual void ProcessEndPath(GREndPathNodeBuilder& builder) = 0;
+
+ /// EvalAssume - Called by ConstraintManager. Used to call checker-specific
+ /// logic for handling assumptions on symbolic values.
+ virtual const GRState* ProcessAssume(const GRState *state,
+ SVal cond, bool assumption) = 0;
};
-
}
#endif
diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h
index b57cfd7b5205b..3bcedbefd65c1 100644
--- a/include/clang/Analysis/PathSensitive/MemRegion.h
+++ b/include/clang/Analysis/PathSensitive/MemRegion.h
@@ -65,6 +65,7 @@ public:
BlockTextRegionKind,
BlockDataRegionKind,
CompoundLiteralRegionKind,
+ CXXThisRegionKind,
StringRegionKind,
ElementRegionKind,
// Decl Regions.
@@ -99,17 +100,13 @@ public:
const MemRegion *StripCasts() const;
- bool hasStackStorage() const;
-
- bool hasParametersStorage() const;
-
- bool hasGlobalsStorage() const;
-
bool hasGlobalsOrParametersStorage() const;
- bool hasHeapStorage() const;
-
- bool hasHeapOrStackStorage() const;
+ bool hasStackStorage() const;
+
+ bool hasStackNonParametersStorage() const;
+
+ bool hasStackParametersStorage() const;
virtual void dumpToStream(llvm::raw_ostream& os) const;
@@ -634,6 +631,36 @@ public:
return R->getKind() == VarRegionKind;
}
};
+
+/// CXXThisRegion - Represents the region for the implicit 'this' parameter
+/// in a call to a C++ method. This region doesn't represent the object
+/// referred to by 'this', but rather 'this' itself.
+class CXXThisRegion : public TypedRegion {
+ friend class MemRegionManager;
+ CXXThisRegion(const PointerType *thisPointerTy,
+ const MemRegion *sReg)
+ : TypedRegion(sReg, CXXThisRegionKind), ThisPointerTy(thisPointerTy) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const PointerType *PT,
+ const MemRegion *sReg);
+
+ void Profile(llvm::FoldingSetNodeID &ID) const;
+
+public:
+ QualType getValueType(ASTContext &C) const {
+ return QualType(ThisPointerTy, 0);
+ }
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == CXXThisRegionKind;
+ }
+
+private:
+ const PointerType *ThisPointerTy;
+};
class FieldRegion : public DeclRegion {
friend class MemRegionManager;
@@ -725,21 +752,21 @@ public:
}
};
+// C++ temporary object associated with an expression.
class CXXObjectRegion : public TypedRegion {
friend class MemRegionManager;
- // T - The object type.
- QualType T;
+ Expr const *Ex;
- CXXObjectRegion(QualType t, const MemRegion *sReg)
- : TypedRegion(sReg, CXXObjectRegionKind), T(t) {}
+ CXXObjectRegion(Expr const *E, MemRegion const *sReg)
+ : TypedRegion(sReg, CXXObjectRegionKind), Ex(E) {}
static void ProfileRegion(llvm::FoldingSetNodeID &ID,
- QualType T, const MemRegion *sReg);
+ Expr const *E, const MemRegion *sReg);
public:
QualType getValueType(ASTContext& C) const {
- return T;
+ return Ex->getType();
}
void Profile(llvm::FoldingSetNodeID &ID) const;
@@ -824,6 +851,11 @@ public:
const CompoundLiteralRegion*
getCompoundLiteralRegion(const CompoundLiteralExpr* CL,
const LocationContext *LC);
+
+ /// getCXXThisRegion - Retrieve the [artifical] region associated with the
+ /// parameter 'this'.
+ const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy,
+ const LocationContext *LC);
/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
const SymbolicRegion* getSymbolicRegion(SymbolRef sym);
@@ -869,7 +901,8 @@ public:
const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd,
const MemRegion* superRegion);
- const CXXObjectRegion *getCXXObjectRegion(QualType T);
+ const CXXObjectRegion *getCXXObjectRegion(Expr const *Ex,
+ LocationContext const *LC);
const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD);
const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD,
diff --git a/include/clang/Analysis/PathSensitive/SValuator.h b/include/clang/Analysis/PathSensitive/SValuator.h
index e63eb12cf8ea8..4a4b502c62713 100644
--- a/include/clang/Analysis/PathSensitive/SValuator.h
+++ b/include/clang/Analysis/PathSensitive/SValuator.h
@@ -28,8 +28,10 @@ class SValuator {
protected:
ValueManager &ValMgr;
+public:
+ // FIXME: Make these protected again one RegionStoreManager correctly
+ // handles loads from differening bound value types.
virtual SVal EvalCastNL(NonLoc val, QualType castTy) = 0;
-
virtual SVal EvalCastL(Loc val, QualType castTy) = 0;
public:
diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h
index 52d73da15bc14..70c17accb7258 100644
--- a/include/clang/Analysis/PathSensitive/Store.h
+++ b/include/clang/Analysis/PathSensitive/Store.h
@@ -103,9 +103,6 @@ public:
virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base)=0;
- // T - the object type.
- Loc getThisObject(QualType T);
-
// FIXME: Make out-of-line.
virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state,
const MemRegion *region) {
@@ -192,7 +189,8 @@ protected:
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
/// implicit casts that arise from loads from regions that are reinterpreted
/// as another region.
- SVal CastRetrievedVal(SVal val, const TypedRegion *R, QualType castTy);
+ SVal CastRetrievedVal(SVal val, const TypedRegion *R, QualType castTy,
+ bool performTestOnly = true);
};
// FIXME: Do we still need this?
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index a2ccea7525ac4..c5d6d7c713166 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -781,6 +781,11 @@ public:
/// formal arguments into the %0 slots. The result is appended onto the Str
/// array.
void FormatDiagnostic(llvm::SmallVectorImpl &OutStr) const;
+
+ /// FormatDiagnostic - Format the given format-string into the
+ /// output buffer using the arguments stored in this diagnostic.
+ void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
+ llvm::SmallVectorImpl &OutStr) const;
};
/// DiagnosticClient - This is an abstract interface implemented by clients of
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index efbc787ef0eeb..dfb6f8ddc1da6 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -81,5 +81,7 @@ def warn_drv_clang_unsupported : Warning<
"the clang compiler does not support '%0'">;
def warn_drv_assuming_mfloat_abi_is : Warning<
"unknown platform, assuming -mfloat-abi=%0">;
+def warn_ignoring_ftabstop_value : Warning<
+ "ignoring invalid -ftabstop value '%0', using default value %1">;
}
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index d8b5f2dad3c96..26a80b51c852f 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -84,6 +84,9 @@ def err_exponent_has_no_digits : Error<"exponent has no digits">;
def ext_imaginary_constant : Extension<"imaginary constants are an extension">;
def err_hexconstant_requires_exponent : Error<
"hexadecimal floating constants require an exponent">;
+def ext_hexconstant_cplusplus : ExtWarn<
+ "hexadecimal floating constants are a C99 feature that is incompatible with "
+ "C++0x">;
def ext_hexconstant_invalid : Extension<
"hexadecimal floating constants are a C99 feature">;
def ext_binary_literal : Extension<
@@ -169,6 +172,9 @@ def err_pp_hash_error : Error<"#error%0">;
def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal;
def err_pp_error_opening_file : Error<
"error opening file '%0': %1">, DefaultFatal;
+def warn_pp_relative_include_from_framework : Warning<
+ "published framework headers should always #import headers within the "
+ "framework with framework paths">, InGroup>;
def err_pp_empty_filename : Error<"empty filename">;
def err_pp_include_too_deep : Error<"#include nested too deeply">;
def err_pp_expects_filename : Error<"expected \"FILENAME\" or ">;
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 98a74a5a03952..c6d0605252853 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -261,6 +261,8 @@ def err_attributes_not_allowed : Error<"an attribute list cannot appear here">;
/// C++ Templates
def err_expected_template : Error<"expected template">;
+def err_unknown_template_name : Error<
+ "unknown template name %0">;
def err_expected_comma_greater : Error<
"expected ',' or '>' in template-parameter-list">;
def err_expected_type_id_after : Error<"expected type-id after '%0'">;
@@ -289,6 +291,16 @@ def err_explicit_instantiation_with_definition : Error<
"definition is meant to be an explicit specialization, add '<>' after the "
"'template' keyword">;
+// Constructor template diagnostics.
+def err_out_of_line_constructor_template_id : Error<
+ "out-of-line constructor for %0 cannot have template arguments">;
+def err_out_of_line_template_id_names_constructor : Error<
+ "qualified reference to %0 is a constructor name rather than a "
+ "template name wherever a constructor can be declared">;
+def err_out_of_line_type_names_constructor : Error<
+ "qualified reference to %0 is a constructor name rather than a "
+ "type wherever a constructor can be declared">;
+
def err_expected_qualified_after_typename : Error<
"expected a qualified name after 'typename'">;
def err_typename_refers_to_non_type_template : Error<
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 155633b08f3b3..7e59f88fcef5c 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -89,7 +89,7 @@ def warn_decl_in_param_list : Warning<
def warn_implicit_function_decl : Warning<
"implicit declaration of function %0">,
InGroup, DefaultIgnore;
-def ext_implicit_function_decl : Extension<
+def ext_implicit_function_decl : ExtWarn<
"implicit declaration of function %0 is invalid in C99">,
InGroup;
@@ -160,6 +160,8 @@ def warn_suggest_noreturn_function : Warning<
def warn_suggest_noreturn_block : Warning<
"block could be attribute 'noreturn'">,
InGroup>, DefaultIgnore;
+def warn_unreachable : Warning<"will never be executed">,
+ InGroup>, DefaultIgnore;
/// Built-in functions.
def ext_implicit_lib_function_decl : ExtWarn<
@@ -683,6 +685,8 @@ def err_attribute_not_string : Error<
"argument to %0 attribute was not a string literal">;
def err_attribute_section_invalid_for_target : Error<
"argument to 'section' attribute is not valid for this target: %0">;
+def err_attribute_section_local_variable : Error<
+ "'section' attribute is not valid on local variables">;
def err_attribute_aligned_not_power_of_two : Error<
"requested alignment is not a power of 2">;
def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
@@ -895,18 +899,61 @@ def err_ovl_ambiguous_member_call : Error<
"call to member function %0 is ambiguous">;
def err_ovl_deleted_member_call : Error<
"call to %select{unavailable|deleted}0 member function %1">;
-def err_ovl_candidate : Note<"candidate function">;
-def err_ovl_candidate_not_viable : Note<"function not viable because"
- " of ambiguity in conversion of argument %0">;
+def note_ovl_candidate : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "is the implicit default constructor|"
+ "is the implicit copy constructor|"
+ "is the implicit copy assignment operator}0%1">;
+// Note that we don't treat templates differently for this diagnostic.
+def note_ovl_candidate_arity : Note<"candidate "
+ "%select{function|function|constructor|function|function|constructor|"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "function (the implicit copy assignment operator)}0 not viable: requires"
+ "%select{ at least| at most|}2 %3 argument%s3, but %4 %plural{1:was|:were}4 "
+ "provided">;
+def note_ovl_candidate_deleted : Note<
+ "candidate %select{function|function|constructor|"
+ "function |function |constructor |||}0%1 "
+ "has been explicitly %select{made unavailable|deleted}2">;
+def note_ovl_candidate_bad_conv : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "function (the implicit copy assignment operator)}0%1"
+ " not viable: no known conversion from %2 to %3 for "
+ "%select{%ordinal5 argument|object argument}4">;
+def note_ovl_candidate_bad_addrspace : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "function (the implicit copy assignment operator)}0%1 not viable: "
+ "%select{%ordinal6|'this'}5 argument (%2) is in "
+ "address space %3, but parameter must be in address space %4">;
+def note_ovl_candidate_bad_cvr_this : Note<"candidate "
+ "%select{|function|||function||||"
+ "function (the implicit copy assignment operator)}0 not viable: "
+ "'this' argument has type %2, but method is not marked "
+ "%select{const|volatile|const or volatile|restrict|const or restrict|"
+ "volatile or restrict|const, volatile, or restrict}3">;
+def note_ovl_candidate_bad_cvr : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "function (the implicit copy assignment operator)}0%1 not viable: "
+ "%ordinal4 argument (%2) would lose "
+ "%select{const|volatile|const and volatile|restrict|const and restrict|"
+ "volatile and restrict|const, volatile, and restrict}3 qualifier"
+ "%select{||s||s|s|s}3">;
def note_ambiguous_type_conversion: Note<
"because of ambiguity in conversion of %0 to %1">;
-def err_ovl_template_candidate : Note<
- "candidate function template specialization %0">;
-def err_ovl_candidate_deleted : Note<
- "candidate function has been explicitly %select{made unavailable|deleted}0">;
-def err_ovl_builtin_binary_candidate : Note<
+def note_ovl_builtin_binary_candidate : Note<
"built-in candidate %0">;
-def err_ovl_builtin_unary_candidate : Note<
+def note_ovl_builtin_unary_candidate : Note<
"built-in candidate %0">;
def err_ovl_no_viable_function_in_init : Error<
"no matching constructor for initialization of %0">;
@@ -920,6 +967,10 @@ def err_ovl_ambiguous_oper : Error<
def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">;
def err_ovl_deleted_oper : Error<
"overload resolution selected %select{unavailable|deleted}0 operator '%1'">;
+def err_ovl_no_viable_subscript :
+ Error<"no viable overloaded operator[] for type %0">;
+def err_ovl_no_oper :
+ Error<"type %0 does not provide a %select{subscript|call}1 operator">;
def err_ovl_no_viable_object_call : Error<
"no matching function for call to object of type %0">;
@@ -927,7 +978,7 @@ def err_ovl_ambiguous_object_call : Error<
"call to object of type %0 is ambiguous">;
def err_ovl_deleted_object_call : Error<
"call to %select{unavailable|deleted}0 function call operator in type %1">;
-def err_ovl_surrogate_cand : Note<"conversion candidate of type %0">;
+def note_ovl_surrogate_cand : Note<"conversion candidate of type %0">;
def err_member_call_without_object : Error<
"call to non-static member function without an object argument">;
@@ -1295,6 +1346,8 @@ def err_template_kw_refers_to_class_template : Error<
"'%0%1' instantiated to a class template, not a function template">;
def note_referenced_class_template : Error<
"class template declared here">;
+def err_template_kw_missing : Error<
+ "missing 'template' keyword prior to dependent template name '%0%1'">;
// C++0x Variadic Templates
def err_template_param_pack_default_arg : Error<
@@ -1472,7 +1525,7 @@ def note_protected_by___block : Note<
"jump bypasses setup of __block variable">;
def err_func_returning_array_function : Error<
- "function cannot return array or function type %0">;
+ "function cannot return %select{array|function}0 type %1">;
def err_field_declared_as_function : Error<"field %0 declared as a function">;
def err_field_incomplete : Error<"field has incomplete type %0">;
def ext_variable_sized_type_in_struct : ExtWarn<
@@ -1543,15 +1596,17 @@ def warn_floatingpoint_eq : Warning<
"comparing floating point with == or != is unsafe">,
InGroup>, DefaultIgnore;
-def warn_shift_negative : Warning<
- "shift count is negative">;
-def warn_shift_gt_typewidth : Warning<
- "shift count >= width of type">;
+def warn_division_by_zero : Warning<"division by zero is undefined">;
+def warn_remainder_by_zero : Warning<"remainder by zero is undefined">;
+def warn_shift_negative : Warning<"shift count is negative">;
+def warn_shift_gt_typewidth : Warning<"shift count >= width of type">;
def warn_precedence_bitwise_rel : Warning<
"%0 has lower precedence than %1; %1 will be evaluated first">,
InGroup;
-
+def note_precedence_bitwise_first : Note<
+ "place parentheses around the %0 expression to evaluate it first">;
+
def err_sizeof_nonfragile_interface : Error<
"invalid application of '%select{alignof|sizeof}1' to interface %0 in "
"non-fragile ABI">;
@@ -1647,6 +1702,8 @@ def err_static_block_func : Error<
def err_typecheck_address_of : Error<"address of %0 requested">;
def ext_typecheck_addrof_void : Extension<
"ISO C forbids taking the address of an expression of type 'void'">;
+def err_unqualified_pointer_member_function : Error<
+ "must explicitly qualify member function %0 when taking its address">;
def err_typecheck_invalid_lvalue_addrof : Error<
"address expression must be an lvalue or a function designator">;
def err_typecheck_unary_expr : Error<
@@ -1721,6 +1778,10 @@ def warn_printf_nonliteral : Warning<
def err_unexpected_interface : Error<
"unexpected interface name %0: expected expression">;
def err_ref_non_value : Error<"%0 does not refer to a value">;
+def err_ref_vm_type : Error<
+ "cannot refer to declaration with a variably modified type inside block">;
+def err_ref_array_type : Error<
+ "cannot refer to declaration with an array type inside block">;
def err_property_not_found : Error<
"property %0 not found on object of type %1">;
def err_duplicate_property : Error<
@@ -1952,6 +2013,8 @@ def warn_condition_is_assignment : Warning<"using the result of an "
def warn_condition_is_idiomatic_assignment : Warning<"using the result "
"of an assignment as a condition without parentheses">,
InGroup>, DefaultIgnore;
+def note_condition_assign_to_comparison : Note<
+ "use '==' to turn this assignment into an equality comparison">;
def warn_value_always_zero : Warning<
"%0 is always %select{zero|false|NULL}1 in this context">;
@@ -2303,6 +2366,13 @@ def err_operator_delete_dependent_param_type : Error<
def err_operator_delete_param_type : Error<
"%0 takes type %1 as first parameter">;
+// C++ literal operators
+def err_literal_operator_outside_namespace : Error<
+ "literal operator %0 must be in a namespace or global scope">;
+// FIXME: This diagnostic sucks
+def err_literal_operator_params : Error<
+ "parameter declaration for literal operator %0 is not valid">;
+
// C++ conversion functions
def err_conv_function_not_member : Error<
"conversion function must be a non-static member function">;
@@ -2569,7 +2639,21 @@ def err_mem_init_not_member_or_class_suggest : Error<
def err_field_designator_unknown_suggest : Error<
"field designator %0 does not refer to any field in type %1; did you mean "
"%2?">;
-
+def err_typecheck_member_reference_ivar_suggest : Error<
+ "%0 does not have a member named %1; did you mean %2?">;
+def err_property_not_found_suggest : Error<
+ "property %0 not found on object of type %1; did you mean %2?">;
+def err_undef_interface_suggest : Error<
+ "cannot find interface declaration for %0; did you mean %1?">;
+def warn_undef_interface_suggest : Warning<
+ "cannot find interface declaration for %0; did you mean %1?">;
+def err_undef_superclass_suggest : Error<
+ "cannot find interface declaration for %0, superclass of %1; did you mean "
+ "%2?">;
+def err_undeclared_protocol_suggest : Error<
+ "cannot find protocol declaration for %0; did you mean %1?">;
+def note_base_class_specified_here : Note<
+ "base class %0 specified here">;
}
diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h
index ae11a755cce4d..0d970123f7458 100644
--- a/include/clang/Basic/PartialDiagnostic.h
+++ b/include/clang/Basic/PartialDiagnostic.h
@@ -26,7 +26,8 @@ class DeclarationName;
class PartialDiagnostic {
struct Storage {
- Storage() : NumDiagArgs(0), NumDiagRanges(0) { }
+ Storage() : NumDiagArgs(0), NumDiagRanges(0), NumCodeModificationHints(0) {
+ }
enum {
/// MaxArguments - The maximum number of arguments we can hold. We
@@ -42,6 +43,10 @@ class PartialDiagnostic {
/// NumDiagRanges - This is the number of ranges in the DiagRanges array.
unsigned char NumDiagRanges;
+ /// \brief The number of code modifications hints in the
+ /// CodeModificationHints array.
+ unsigned char NumCodeModificationHints;
+
/// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
/// values, with one for each argument. This specifies whether the argument
/// is in DiagArgumentsStr or in DiagArguments.
@@ -56,6 +61,12 @@ class PartialDiagnostic {
/// DiagRanges - The list of ranges added to this diagnostic. It currently
/// only support 10 ranges, could easily be extended if needed.
SourceRange DiagRanges[10];
+
+ enum { MaxCodeModificationHints = 3 };
+
+ /// CodeModificationHints - If valid, provides a hint with some code
+ /// to insert, remove, or modify at a particular position.
+ CodeModificationHint CodeModificationHints[MaxCodeModificationHints];
};
/// DiagID - The diagnostic ID.
@@ -84,6 +95,20 @@ class PartialDiagnostic {
DiagStorage->DiagRanges[DiagStorage->NumDiagRanges++] = R;
}
+ void AddCodeModificationHint(const CodeModificationHint &Hint) const {
+ if (Hint.isNull())
+ return;
+
+ if (!DiagStorage)
+ DiagStorage = new Storage;
+
+ assert(DiagStorage->NumCodeModificationHints <
+ Storage::MaxCodeModificationHints &&
+ "Too many code modification hints!");
+ DiagStorage->CodeModificationHints[DiagStorage->NumCodeModificationHints++]
+ = Hint;
+ }
+
public:
PartialDiagnostic(unsigned DiagID)
: DiagID(DiagID), DiagStorage(0) { }
@@ -130,6 +155,10 @@ public:
// Add all ranges.
for (unsigned i = 0, e = DiagStorage->NumDiagRanges; i != e; ++i)
DB.AddSourceRange(DiagStorage->DiagRanges[i]);
+
+ // Add all code modification hints
+ for (unsigned i = 0, e = DiagStorage->NumCodeModificationHints; i != e; ++i)
+ DB.AddCodeModificationHint(DiagStorage->CodeModificationHints[i]);
}
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
@@ -165,6 +194,13 @@ public:
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
DeclarationName N);
+
+ friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const CodeModificationHint &Hint) {
+ PD.AddCodeModificationHint(Hint);
+ return PD;
+ }
+
};
inline PartialDiagnostic PDiag(unsigned DiagID = 0) {
diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h
index 36baf5feecce2..d4f557b57d0b3 100644
--- a/include/clang/Basic/SourceLocation.h
+++ b/include/clang/Basic/SourceLocation.h
@@ -162,6 +162,7 @@ public:
void setEnd(SourceLocation e) { E = e; }
bool isValid() const { return B.isValid() && E.isValid(); }
+ bool isInvalid() const { return !isValid(); }
bool operator==(const SourceRange &X) const {
return B == X.B && E == X.E;
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 0d95e6a603235..97e0495bfbe20 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -30,6 +30,7 @@ class StringRef;
namespace clang {
class Diagnostic;
class LangOptions;
+class MacroBuilder;
class SourceLocation;
class SourceManager;
class TargetOptions;
@@ -209,7 +210,7 @@ public:
/// getTargetDefines - Appends the target-specific #define values for this
/// target set to the specified buffer.
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &DefineBuffer) const = 0;
+ MacroBuilder &Builder) const = 0;
/// getTargetBuiltins - Return information about target-specific builtins for
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 6a0d816920455..2511dfb7677af 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -178,6 +178,8 @@ def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-rang
HelpText<"Print source range spans in numeric form">;
def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">,
HelpText<"Print diagnostic name with mappable diagnostics">;
+def ftabstop : Separate<"-ftabstop">, MetaVarName<"">,
+ HelpText<"Set the tab stop distance.">;
def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"">,
HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
def fcolor_diagnostics : Flag<"-fcolor-diagnostics">,
@@ -323,6 +325,8 @@ def fgnu_runtime : Flag<"-fgnu-runtime">,
HelpText<"Generate output compatible with the standard GNU Objective-C runtime">;
def std_EQ : Joined<"-std=">,
HelpText<"Language standard to compile for">;
+def fmath_errno : Flag<"-fmath-errno">,
+ HelpText<"Require math functions to indicate errors by setting errno">;
def fms_extensions : Flag<"-fms-extensions">,
HelpText<"Accept some non-standard constructs used in Microsoft header files ">;
def main_file_name : Separate<"-main-file-name">,
@@ -331,8 +335,6 @@ def fno_elide_constructors : Flag<"-fno-elide-constructors">,
HelpText<"Disable C++ copy constructor elision">;
def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">,
HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">;
-def fno_math_errno : Flag<"-fno-math-errno">,
- HelpText<"Don't require math functions to respect errno">;
def fno_signed_char : Flag<"-fno-signed-char">,
HelpText<"Char is unsigned">;
def fno_operator_names : Flag<"-fno-operator-names">,
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 247e1f5117f9a..955d98e4e9142 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -345,6 +345,7 @@ def fstack_protector_all : Flag<"-fstack-protector-all">, Group;
def fstack_protector : Flag<"-fstack-protector">, Group;
def fstrict_aliasing : Flag<"-fstrict-aliasing">, Group;
def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>;
+def ftabstop_EQ : Joined<"-ftabstop=">, Group;
def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group;
def fterminated_vtables : Flag<"-fterminated-vtables">, Group;
def ftime_report : Flag<"-ftime-report">, Group;
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index b3c2d05ef5634..cc8d438db3e96 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -87,10 +87,6 @@ public:
// Platform defaults information
- /// IsMathErrnoDefault - Does this tool chain set -fmath-errno by
- /// default.
- virtual bool IsMathErrnoDefault() const = 0;
-
/// IsBlocksDefault - Does this tool chain enable -fblocks by default.
virtual bool IsBlocksDefault() const { return false; }
diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def
index e01a04c67ae1f..d66fe9221a301 100644
--- a/include/clang/Driver/Types.def
+++ b/include/clang/Driver/Types.def
@@ -41,6 +41,7 @@
// C family source language (with and without preprocessing).
TYPE("cpp-output", PP_C, INVALID, "i", "u")
TYPE("c", C, PP_C, 0, "u")
+TYPE("cl", CL, PP_C, 0, "u")
TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", "u")
TYPE("objective-c", ObjC, PP_ObjC, 0, "u")
TYPE("c++-cpp-output", PP_CXX, INVALID, "ii", "u")
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index 18ec429db7e8e..edafe623a4f6c 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -32,6 +32,7 @@ class Diagnostic;
class DiagnosticClient;
class ExternalASTSource;
class FileManager;
+class FrontendAction;
class Preprocessor;
class Source;
class SourceManager;
@@ -103,6 +104,42 @@ public:
bool _OwnsLLVMContext = true);
~CompilerInstance();
+ /// @name High-Level Operations
+ /// {
+
+ /// ExecuteAction - Execute the provided action against the compiler's
+ /// CompilerInvocation object.
+ ///
+ /// This function makes the following assumptions:
+ ///
+ /// - The invocation options should be initialized. This function does not
+ /// handle the '-help' or '-version' options, clients should handle those
+ /// directly.
+ ///
+ /// - The diagnostics engine should have already been created by the client.
+ ///
+ /// - No other CompilerInstance state should have been initialized (this is
+ /// an unchecked error).
+ ///
+ /// - Clients should have initialized any LLVM target features that may be
+ /// required.
+ ///
+ /// - Clients should eventually call llvm_shutdown() upon the completion of
+ /// this routine to ensure that any managed objects are properly destroyed.
+ ///
+ /// Note that this routine may write output to 'stderr'.
+ ///
+ /// \param Act - The action to execute.
+ /// \return - True on success.
+ //
+ // FIXME: This function should take the stream to write any debugging /
+ // verbose output to as an argument.
+ //
+ // FIXME: Eliminate the llvm_shutdown requirement, that should either be part
+ // of the context or else not CompilerInstance specific.
+ bool ExecuteAction(FrontendAction &Act);
+
+ /// }
/// @name LLVM Context
/// {
@@ -451,6 +488,7 @@ public:
const HeaderSearchOptions &,
const DependencyOutputOptions &,
const TargetInfo &,
+ const FrontendOptions &,
SourceManager &, FileManager &);
/// Create the AST context.
diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h
index 6346dc0bfdec0..13039bb5063e1 100644
--- a/include/clang/Frontend/DiagnosticOptions.h
+++ b/include/clang/Frontend/DiagnosticOptions.h
@@ -35,6 +35,10 @@ public:
/// diagnostics, indicated by markers in the
/// input source file.
+ /// The distance between tab stops.
+ unsigned TabStop;
+ enum { DefaultTabStop = 8, MaxTabStop = 100 };
+
/// Column limit for formatting message diagnostics, or 0 if unused.
unsigned MessageLength;
@@ -49,6 +53,7 @@ public:
public:
DiagnosticOptions() {
IgnoreWarnings = 0;
+ TabStop = DefaultTabStop;
MessageLength = 0;
NoRewriteMacros = 0;
Pedantic = 0;
diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h
index 7e2c65690fd69..9665ce189f4aa 100644
--- a/include/clang/Frontend/PCHReader.h
+++ b/include/clang/Frontend/PCHReader.h
@@ -20,6 +20,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Type.h"
#include "clang/AST/TemplateBase.h"
+#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceManager.h"
@@ -146,7 +147,8 @@ public:
/// required when traversing the AST. Only those AST nodes that are
/// actually required will be de-serialized.
class PCHReader
- : public ExternalSemaSource,
+ : public ExternalPreprocessorSource,
+ public ExternalSemaSource,
public IdentifierInfoLookup,
public ExternalIdentifierLookup,
public ExternalSLocEntrySource {
@@ -183,6 +185,10 @@ private:
llvm::BitstreamReader StreamFile;
llvm::BitstreamCursor Stream;
+ /// \brief The cursor to the start of the preprocessor block, which stores
+ /// all of the macro definitions.
+ llvm::BitstreamCursor MacroCursor;
+
/// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It
/// has read all the abbreviations at the start of the block and is ready to
/// jump around with these in context.
@@ -634,8 +640,7 @@ public:
/// This routine builds a new IdentifierInfo for the given identifier. If any
/// declarations with this name are visible from translation unit scope, their
/// declarations will be deserialized and introduced into the declaration
- /// chain of the identifier. FIXME: if this identifier names a macro,
- /// deserialize the macro.
+ /// chain of the identifier.
virtual IdentifierInfo* get(const char *NameStart, const char *NameEnd);
IdentifierInfo* get(llvm::StringRef Name) {
return get(Name.begin(), Name.end());
@@ -712,6 +717,9 @@ public:
/// \brief Reads the macro record located at the given offset.
void ReadMacroRecord(uint64_t Offset);
+ /// \brief Read the set of macros defined by this external macro source.
+ virtual void ReadDefinedMacros();
+
/// \brief Retrieve the AST context that this PCH reader
/// supplements.
ASTContext *getContext() { return Context; }
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index 27c14c9170159..c8df4941cc213 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -15,13 +15,11 @@
#define LLVM_CLANG_FRONTEND_UTILS_H
#include "llvm/ADT/StringRef.h"
-#include
-#include
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
namespace llvm {
class Triple;
-class raw_ostream;
-class raw_fd_ostream;
}
namespace clang {
@@ -41,6 +39,29 @@ class PreprocessorOutputOptions;
class SourceManager;
class Stmt;
class TargetInfo;
+class FrontendOptions;
+
+class MacroBuilder {
+ llvm::raw_ostream &Out;
+public:
+ MacroBuilder(llvm::raw_ostream &Output) : Out(Output) {}
+
+ /// Append a #define line for macro of the form "#define Name Value\n".
+ void defineMacro(const llvm::Twine &Name, const llvm::Twine &Value = "1") {
+ Out << "#define " << Name << ' ' << Value << '\n';
+ }
+
+ /// Append a #undef line for Name. Name should be of the form XXX
+ /// and we emit "#undef XXX".
+ void undefineMacro(const llvm::Twine &Name) {
+ Out << "#undef " << Name << '\n';
+ }
+
+ /// Directly append Str and a newline to the underlying buffer.
+ void append(const llvm::Twine &Str) {
+ Out << Str << '\n';
+ }
+};
/// Normalize \arg File for use in a user defined #include directive (in the
/// predefines buffer).
@@ -56,7 +77,8 @@ void ApplyHeaderSearchOptions(HeaderSearch &HS,
/// environment ready to process a single file.
void InitializePreprocessor(Preprocessor &PP,
const PreprocessorOptions &PPOpts,
- const HeaderSearchOptions &HSOpts);
+ const HeaderSearchOptions &HSOpts,
+ const FrontendOptions &FEOpts);
/// ProcessWarningOptions - Initialize the diagnostic client and process the
/// warning options specified on the command line.
diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h
index c94a990224155..64687a18e2b63 100644
--- a/include/clang/Lex/DirectoryLookup.h
+++ b/include/clang/Lex/DirectoryLookup.h
@@ -16,6 +16,9 @@
#include "clang/Basic/SourceManager.h"
+namespace llvm {
+ class StringRef;
+}
namespace clang {
class HeaderMap;
class DirectoryEntry;
@@ -118,12 +121,10 @@ public:
/// LookupFile - Lookup the specified file in this search path, returning it
/// if it exists or returning null if not.
- const FileEntry *LookupFile(const char *FilenameStart,
- const char *FilenameEnd, HeaderSearch &HS) const;
+ const FileEntry *LookupFile(llvm::StringRef Filename, HeaderSearch &HS) const;
private:
- const FileEntry *DoFrameworkLookup(const char *FilenameStart,
- const char *FilenameEnd,
+ const FileEntry *DoFrameworkLookup(llvm::StringRef Filename,
HeaderSearch &HS) const;
};
diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h
new file mode 100644
index 0000000000000..af5c3898161e4
--- /dev/null
+++ b/include/clang/Lex/ExternalPreprocessorSource.h
@@ -0,0 +1,34 @@
+//===- ExternalPreprocessorSource.h - Abstract Macro Interface --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ExternalPreprocessorSource interface, which enables
+// construction of macro definitions from some external source.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LEX_EXTERNAL_PREPROCESSOR_SOURCE_H
+#define LLVM_CLANG_LEX_EXTERNAL_PREPROCESSOR_SOURCE_H
+
+namespace clang {
+
+/// \brief Abstract interface for external sources of preprocessor
+/// information.
+///
+/// This abstract class allows an external sources (such as the \c PCHReader)
+/// to provide additional macro definitions.
+class ExternalPreprocessorSource {
+public:
+ virtual ~ExternalPreprocessorSource();
+
+ /// \brief Read the set of macros defined by this external macro source.
+ virtual void ReadDefinedMacros() = 0;
+};
+
+}
+
+#endif // LLVM_CLANG_LEX_EXTERNAL_PREPROCESSOR_SOURCE_H
diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h
index 6bb7c25947d7c..9837e296535f1 100644
--- a/include/clang/Lex/HeaderMap.h
+++ b/include/clang/Lex/HeaderMap.h
@@ -16,6 +16,7 @@
namespace llvm {
class MemoryBuffer;
+ class StringRef;
}
namespace clang {
class FileEntry;
@@ -46,8 +47,7 @@ public:
/// LookupFile - Check to see if the specified relative filename is located in
/// this HeaderMap. If so, open it and return its FileEntry.
- const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd,
- FileManager &FM) const;
+ const FileEntry *LookupFile(llvm::StringRef Filename, FileManager &FM) const;
/// getFileName - Return the filename of the headermap.
const char *getFileName() const;
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 7517440983b12..16b8379045e59 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -150,8 +150,7 @@ public:
/// search location. This is used to implement #include_next. CurFileEnt, if
/// non-null, indicates where the #including file is, in case a relative
/// search is needed.
- const FileEntry *LookupFile(const char *FilenameStart,
- const char *FilenameEnd, bool isAngled,
+ const FileEntry *LookupFile(llvm::StringRef Filename, bool isAngled,
const DirectoryLookup *FromDir,
const DirectoryLookup *&CurDir,
const FileEntry *CurFileEnt);
@@ -161,16 +160,14 @@ public:
/// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox
/// is a subframework within Carbon.framework. If so, return the FileEntry
/// for the designated file, otherwise return null.
- const FileEntry *LookupSubframeworkHeader(const char *FilenameStart,
- const char *FilenameEnd,
+ const FileEntry *LookupSubframeworkHeader(llvm::StringRef Filename,
const FileEntry *RelativeFileEnt);
/// LookupFrameworkCache - Look up the specified framework name in our
/// framework cache, returning the DirectoryEntry it is in if we know,
/// otherwise, return null.
- const DirectoryEntry *&LookupFrameworkCache(const char *FWNameStart,
- const char *FWNameEnd) {
- return FrameworkMap.GetOrCreateValue(FWNameStart, FWNameEnd).getValue();
+ const DirectoryEntry *&LookupFrameworkCache(llvm::StringRef FWName) {
+ return FrameworkMap.GetOrCreateValue(FWName).getValue();
}
/// ShouldEnterIncludeFile - Mark the specified file as a target of of a
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 7c838ff862437..fc2671f481125 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -32,6 +32,7 @@
namespace clang {
class SourceManager;
+class ExternalPreprocessorSource;
class FileManager;
class FileEntry;
class HeaderSearch;
@@ -42,7 +43,7 @@ class ScratchBuffer;
class TargetInfo;
class PPCallbacks;
class DirectoryLookup;
-
+
/// Preprocessor - This object engages in a tight little dance with the lexer to
/// efficiently preprocess tokens. Lexers know only about tokens within a
/// single source file, and don't know anything about preprocessor-level issues
@@ -57,6 +58,9 @@ class Preprocessor {
ScratchBuffer *ScratchBuf;
HeaderSearch &HeaderInfo;
+ /// \brief External source of macros.
+ ExternalPreprocessorSource *ExternalSource;
+
/// PTH - An optional PTHManager object used for getting tokens from
/// a token cache rather than lexing the original source file.
llvm::OwningPtr PTH;
@@ -99,6 +103,9 @@ class Preprocessor {
/// DisableMacroExpansion - True if macro expansion is disabled.
bool DisableMacroExpansion : 1;
+ /// \brief Whether we have already loaded macros from the external source.
+ mutable bool ReadMacrosFromExternalSource : 1;
+
/// Identifiers - This is mapping/lookup information for all identifiers in
/// the program, including program keywords.
mutable IdentifierTable Identifiers;
@@ -247,6 +254,14 @@ public:
PTHManager *getPTHManager() { return PTH.get(); }
+ void setExternalSource(ExternalPreprocessorSource *Source) {
+ ExternalSource = Source;
+ }
+
+ ExternalPreprocessorSource *getExternalSource() const {
+ return ExternalSource;
+ }
+
/// SetCommentRetentionState - Control whether or not the preprocessor retains
/// comments in output.
void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) {
@@ -296,11 +311,9 @@ public:
/// state of the macro table. This visits every currently-defined macro.
typedef llvm::DenseMap::const_iterator macro_iterator;
- macro_iterator macro_begin() const { return Macros.begin(); }
- macro_iterator macro_end() const { return Macros.end(); }
-
-
-
+ macro_iterator macro_begin(bool IncludeExternalMacros = true) const;
+ macro_iterator macro_end(bool IncludeExternalMacros = true) const;
+
const std::string &getPredefines() const { return Predefines; }
/// setPredefines - Set the predefines for this Preprocessor. These
/// predefines are automatically injected when parsing the main file.
@@ -678,14 +691,14 @@ public:
/// caller is expected to provide a buffer that is large enough to hold the
/// spelling of the filename, but is also expected to handle the case when
/// this method decides to use a different buffer.
- bool GetIncludeFilenameSpelling(SourceLocation Loc,
- const char *&BufStart, const char *&BufEnd);
+ bool GetIncludeFilenameSpelling(SourceLocation Loc,llvm::StringRef &Filename);
/// LookupFile - Given a "foo" or reference, look up the indicated file,
/// return null on failure. isAngled indicates whether the file reference is
/// for system #include's or not (i.e. using <> instead of "").
- const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd,
- bool isAngled, const DirectoryLookup *FromDir,
+ const FileEntry *LookupFile(llvm::StringRef Filename,
+ SourceLocation FilenameTokLoc, bool isAngled,
+ const DirectoryLookup *FromDir,
const DirectoryLookup *&CurDir);
/// GetCurLookup - The DirectoryLookup structure used to find the current
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 4cbc21ad014ae..7209e0a843cd1 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -291,6 +291,42 @@ public:
bool EnteringContext,
TemplateTy &Template) = 0;
+ /// \brief Action called as part of error recovery when the parser has
+ /// determined that the given name must refer to a template, but
+ /// \c isTemplateName() did not return a result.
+ ///
+ /// This callback permits the action to give a detailed diagnostic when an
+ /// unknown template name is encountered and, potentially, to try to recover
+ /// by producing a new template in \p SuggestedTemplate.
+ ///
+ /// \param II the name that should be a template.
+ ///
+ /// \param IILoc the location of the name in the source.
+ ///
+ /// \param S the scope in which name lookup was performed.
+ ///
+ /// \param SS the C++ scope specifier that preceded the name.
+ ///
+ /// \param SuggestedTemplate if the action sets this template to a non-NULL,
+ /// template, the parser will recover by consuming the template name token
+ /// and the template argument list that follows.
+ ///
+ /// \param SuggestedTemplateKind as input, the kind of template that we
+ /// expect (e.g., \c TNK_Type_template or \c TNK_Function_template). If the
+ /// action provides a suggested template, this should be set to the kind of
+ /// template.
+ ///
+ /// \returns true if a diagnostic was emitted, false otherwise. When false,
+ /// the parser itself will emit a generic "unknown template name" diagnostic.
+ virtual bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ const CXXScopeSpec *SS,
+ TemplateTy &SuggestedTemplate,
+ TemplateNameKind &SuggestedKind) {
+ return false;
+ }
+
/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
/// global scope ('::').
virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S,
@@ -866,7 +902,8 @@ public:
MultiExprArg Exprs,
ExprArg AsmString,
MultiExprArg Clobbers,
- SourceLocation RParenLoc) {
+ SourceLocation RParenLoc,
+ bool MSAsm = false) {
return StmtEmpty();
}
@@ -2176,7 +2213,7 @@ public:
// protocols, categories), the parser passes all methods/properties.
// For class implementations, these values default to 0. For implementations,
// methods are processed incrementally (by ActOnMethodDeclaration above).
- virtual void ActOnAtEnd(SourceLocation AtEndLoc,
+ virtual void ActOnAtEnd(SourceRange AtEnd,
DeclPtrTy classDecl,
DeclPtrTy *allMethods = 0,
unsigned allNum = 0,
@@ -2339,11 +2376,49 @@ public:
/// \todo Code completion for attributes.
//@{
+ /// \brief Describes the context in which code completion occurs.
+ enum CodeCompletionContext {
+ /// \brief Code completion occurs at top-level or namespace context.
+ CCC_Namespace,
+ /// \brief Code completion occurs within a class, struct, or union.
+ CCC_Class,
+ /// \brief Code completion occurs within an Objective-C interface, protocol,
+ /// or category.
+ CCC_ObjCInterface,
+ /// \brief Code completion occurs within an Objective-C implementation or
+ /// category implementation
+ CCC_ObjCImplementation,
+ /// \brief Code completion occurs within the list of instance variables
+ /// in an Objective-C interface, protocol, category, or implementation.
+ CCC_ObjCInstanceVariableList,
+ /// \brief Code completion occurs following one or more template
+ /// headers.
+ CCC_Template,
+ /// \brief Code completion occurs following one or more template
+ /// headers within a class.
+ CCC_MemberTemplate,
+ /// \brief Code completion occurs within an expression.
+ CCC_Expression,
+ /// \brief Code completion occurs within a statement, which may
+ /// also be an expression or a declaration.
+ CCC_Statement,
+ /// \brief Code completion occurs at the beginning of the
+ /// initialization statement (or expression) in a for loop.
+ CCC_ForInit,
+ /// \brief Code completion ocurs within the condition of an if,
+ /// while, switch, or for statement.
+ CCC_Condition
+ };
+
/// \brief Code completion for an ordinary name that occurs within the given
/// scope.
///
/// \param S the scope in which the name occurs.
- virtual void CodeCompleteOrdinaryName(Scope *S) { }
+ ///
+ /// \param CompletionContext the context in which code completion
+ /// occurs.
+ virtual void CodeCompleteOrdinaryName(Scope *S,
+ CodeCompletionContext CompletionContext) { }
/// \brief Code completion for a member access expression.
///
@@ -2458,6 +2533,9 @@ public:
virtual void CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl,
bool InInterface) { }
+ /// \brief Code completion after the '@' in the list of instance variables.
+ virtual void CodeCompleteObjCAtVisibility(Scope *S) { }
+
/// \brief Code completion after the '@' in a statement.
virtual void CodeCompleteObjCAtStatement(Scope *S) { }
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h
index 7c99e3e58254e..6a3d8a924e077 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Parse/DeclSpec.h
@@ -194,6 +194,7 @@ private:
SourceLocation StorageClassSpecLoc, SCS_threadLoc;
SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc;
+ SourceRange TypeofParensRange;
SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc;
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc;
SourceLocation FriendLoc, ConstexprLoc;
@@ -257,6 +258,9 @@ public:
SourceLocation getTypeSpecSignLoc() const { return TSSLoc; }
SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; }
+ SourceRange getTypeofParensRange() const { return TypeofParensRange; }
+ void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; }
+
/// getSpecifierName - Turn a type-specifier-type into a string like "_Bool"
/// or "union".
static const char *getSpecifierName(DeclSpec::TST T);
@@ -493,6 +497,8 @@ public:
IK_LiteralOperatorId,
/// \brief A constructor name.
IK_ConstructorName,
+ /// \brief A constructor named via a template-id.
+ IK_ConstructorTemplateId,
/// \brief A destructor name.
IK_DestructorName,
/// \brief A template-id, e.g., f.
@@ -534,8 +540,9 @@ public:
/// class-name.
ActionBase::TypeTy *DestructorName;
- /// \brief When Kind == IK_TemplateId, the template-id annotation that
- /// contains the template name and template arguments.
+ /// \brief When Kind == IK_TemplateId or IK_ConstructorTemplateId,
+ /// the template-id annotation that contains the template name and
+ /// template arguments.
TemplateIdAnnotation *TemplateId;
};
@@ -648,6 +655,14 @@ public:
ConstructorName = ClassType;
}
+ /// \brief Specify that this unqualified-id was parsed as a
+ /// template-id that names a constructor.
+ ///
+ /// \param TemplateId the template-id annotation that describes the parsed
+ /// template-id. This UnqualifiedId instance will take ownership of the
+ /// \p TemplateId and will free it on destruction.
+ void setConstructorTemplateId(TemplateIdAnnotation *TemplateId);
+
/// \brief Specify that this unqualified-id was parsed as a destructor name.
///
/// \param TildeLoc the location of the '~' that introduces the destructor
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 2214797b8f7b5..0fc9413c30c3e 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -784,7 +784,7 @@ private:
llvm::SmallVector PendingObjCImpDecl;
DeclPtrTy ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
- DeclPtrTy ParseObjCAtEndDeclaration(SourceLocation atLoc);
+ DeclPtrTy ParseObjCAtEndDeclaration(SourceRange atEnd);
DeclPtrTy ParseObjCAtAliasDeclaration(SourceLocation atLoc);
DeclPtrTy ParseObjCPropertySynthesize(SourceLocation atLoc);
DeclPtrTy ParseObjCPropertyDynamic(SourceLocation atLoc);
@@ -1037,7 +1037,8 @@ private:
/// would be best implemented in the parser.
enum DeclSpecContext {
DSC_normal, // normal context
- DSC_class // class context, enables 'friend'
+ DSC_class, // class context, enables 'friend'
+ DSC_top_level // top-level/namespace declaration context
};
DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd,
@@ -1056,6 +1057,7 @@ private:
bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
const ParsedTemplateInfo &TemplateInfo,
AccessSpecifier AS);
+ DeclSpecContext getDeclSpecContextFromDeclaratorContext(unsigned Context);
void ParseDeclarationSpecifiers(DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
AccessSpecifier AS = AS_none,
@@ -1109,6 +1111,11 @@ private:
return isDeclarationSpecifier();
}
+ /// \brief Starting with a scope specifier, identifier, or
+ /// template-id that refers to the current class, determine whether
+ /// this is a constructor declarator.
+ bool isConstructorDeclarator();
+
/// \brief Specifies the context in which type-id/expression
/// disambiguation will occur.
enum TentativeCXXTypeIdContext {
diff --git a/include/clang/Rewrite/Rewriter.h b/include/clang/Rewrite/Rewriter.h
index 29e78fa27958b..1692180a6da9a 100644
--- a/include/clang/Rewrite/Rewriter.h
+++ b/include/clang/Rewrite/Rewriter.h
@@ -146,13 +146,13 @@ public:
/// are in the same file. If not, this returns -1.
int getRangeSize(SourceRange Range) const;
- /// getRewritenText - Return the rewritten form of the text in the specified
+ /// getRewrittenText - Return the rewritten form of the text in the specified
/// range. If the start or end of the range was unrewritable or if they are
/// in different buffers, this returns an empty string.
///
/// Note that this method is not particularly efficient.
///
- std::string getRewritenText(SourceRange Range) const;
+ std::string getRewrittenText(SourceRange Range) const;
/// InsertText - Insert the specified string at the specified location in the
/// original buffer. This method returns true (and does nothing) if the input
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index aec10f32fe632..348917a7d0340 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -85,7 +85,18 @@ public:
/// \brief A right angle bracket ('>').
CK_RightAngle,
/// \brief A comma separator (',').
- CK_Comma
+ CK_Comma,
+ /// \brief A colon (':').
+ CK_Colon,
+ /// \brief A semicolon (';').
+ CK_SemiColon,
+ /// \brief An '=' sign.
+ CK_Equal,
+ /// \brief Horizontal whitespace (' ').
+ CK_HorizontalSpace,
+ /// \brief Verticle whitespace ('\n' or '\r\n', depending on the
+ /// platform).
+ CK_VerticalSpace
};
/// \brief One piece of the code completion string.
@@ -270,10 +281,6 @@ public:
IdentifierInfo *Macro;
};
- /// \brief Describes how good this result is, with zero being the best
- /// result and progressively higher numbers representing poorer results.
- unsigned Rank;
-
/// \brief Specifiers which parameter (of a function, Objective-C method,
/// macro, etc.) we should start with when formatting the result.
unsigned StartParameter;
@@ -298,32 +305,32 @@ public:
NestedNameSpecifier *Qualifier;
/// \brief Build a result that refers to a declaration.
- Result(NamedDecl *Declaration, unsigned Rank,
+ Result(NamedDecl *Declaration,
NestedNameSpecifier *Qualifier = 0,
bool QualifierIsInformative = false)
- : Kind(RK_Declaration), Declaration(Declaration), Rank(Rank),
+ : Kind(RK_Declaration), Declaration(Declaration),
StartParameter(0), Hidden(false),
QualifierIsInformative(QualifierIsInformative),
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
Qualifier(Qualifier) { }
/// \brief Build a result that refers to a keyword or symbol.
- Result(const char *Keyword, unsigned Rank)
- : Kind(RK_Keyword), Keyword(Keyword), Rank(Rank), StartParameter(0),
+ Result(const char *Keyword)
+ : Kind(RK_Keyword), Keyword(Keyword), StartParameter(0),
Hidden(false), QualifierIsInformative(0),
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
Qualifier(0) { }
/// \brief Build a result that refers to a macro.
- Result(IdentifierInfo *Macro, unsigned Rank)
- : Kind(RK_Macro), Macro(Macro), Rank(Rank), StartParameter(0),
+ Result(IdentifierInfo *Macro)
+ : Kind(RK_Macro), Macro(Macro), StartParameter(0),
Hidden(false), QualifierIsInformative(0),
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
Qualifier(0) { }
/// \brief Build a result that refers to a pattern.
- Result(CodeCompletionString *Pattern, unsigned Rank)
- : Kind(RK_Pattern), Pattern(Pattern), Rank(Rank), StartParameter(0),
+ Result(CodeCompletionString *Pattern)
+ : Kind(RK_Pattern), Pattern(Pattern), StartParameter(0),
Hidden(false), QualifierIsInformative(0),
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
Qualifier(0) { }
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp
index 772a884c90d36..50a6e0a50d8bf 100644
--- a/lib/AST/APValue.cpp
+++ b/lib/AST/APValue.cpp
@@ -12,9 +12,20 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/APValue.h"
+#include "clang/AST/CharUnits.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
+namespace {
+ struct LV {
+ Expr* Base;
+ CharUnits Offset;
+ };
+}
+
+APValue::APValue(Expr* B) : Kind(Uninitialized) {
+ MakeLValue(); setLValue(B, CharUnits::Zero());
+}
const APValue &APValue::operator=(const APValue &RHS) {
if (Kind != RHS.Kind) {
@@ -106,3 +117,25 @@ void APValue::print(llvm::raw_ostream &OS) const {
}
}
+Expr* APValue::getLValueBase() const {
+ assert(isLValue() && "Invalid accessor");
+ return ((const LV*)(const void*)Data)->Base;
+}
+
+CharUnits APValue::getLValueOffset() const {
+ assert(isLValue() && "Invalid accessor");
+ return ((const LV*)(const void*)Data)->Offset;
+}
+
+void APValue::setLValue(Expr *B, const CharUnits &O) {
+ assert(isLValue() && "Invalid accessor");
+ ((LV*)(char*)Data)->Base = B;
+ ((LV*)(char*)Data)->Offset = O;
+}
+
+void APValue::MakeLValue() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data) LV();
+ Kind = LValue;
+}
+
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 74e74e7aba0bd..76ec852cb89e5 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -814,10 +814,10 @@ ASTContext::getTypeInfo(const Type *T) {
/// getTypeSizeInChars - Return the size of the specified type, in characters.
/// This method does not work on incomplete types.
CharUnits ASTContext::getTypeSizeInChars(QualType T) {
- return CharUnits::fromRaw(getTypeSize(T) / getCharWidth());
+ return CharUnits::fromQuantity(getTypeSize(T) / getCharWidth());
}
CharUnits ASTContext::getTypeSizeInChars(const Type *T) {
- return CharUnits::fromRaw(getTypeSize(T) / getCharWidth());
+ return CharUnits::fromQuantity(getTypeSize(T) / getCharWidth());
}
/// getPreferredTypeAlign - Return the "preferred" alignment of the specified
@@ -2374,16 +2374,14 @@ CanQualType ASTContext::getCanonicalType(QualType T) {
QualType ASTContext::getUnqualifiedArrayType(QualType T,
Qualifiers &Quals) {
- assert(T.isCanonical() && "Only operates on canonical types");
+ Quals = T.getQualifiers();
if (!isa(T)) {
- Quals = T.getLocalQualifiers();
- return T.getLocalUnqualifiedType();
+ return T.getUnqualifiedType();
}
- assert(!T.hasQualifiers() && "canonical array type has qualifiers!");
const ArrayType *AT = cast(T);
QualType Elt = AT->getElementType();
- QualType UnqualElt = getUnqualifiedArrayType(getCanonicalType(Elt), Quals);
+ QualType UnqualElt = getUnqualifiedArrayType(Elt, Quals);
if (Elt == UnqualElt)
return T;
@@ -2396,12 +2394,6 @@ QualType ASTContext::getUnqualifiedArrayType(QualType T,
return getIncompleteArrayType(UnqualElt, IAT->getSizeModifier(), 0);
}
- if (const VariableArrayType *VAT = dyn_cast(T)) {
- return getVariableArrayType(UnqualElt, VAT->getSizeExpr()->Retain(),
- VAT->getSizeModifier(), 0,
- SourceRange());
- }
-
const DependentSizedArrayType *DSAT = cast(T);
return getDependentSizedArrayType(UnqualElt, DSAT->getSizeExpr()->Retain(),
DSAT->getSizeModifier(), 0,
@@ -3143,16 +3135,21 @@ static bool isTypeTypedefedAsBOOL(QualType T) {
/// getObjCEncodingTypeSize returns size of type for objective-c encoding
/// purpose.
-int ASTContext::getObjCEncodingTypeSize(QualType type) {
- uint64_t sz = getTypeSize(type);
+CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) {
+ CharUnits sz = getTypeSizeInChars(type);
// Make all integer and enum types at least as large as an int
- if (sz > 0 && type->isIntegralType())
- sz = std::max(sz, getTypeSize(IntTy));
+ if (sz.isPositive() && type->isIntegralType())
+ sz = std::max(sz, getTypeSizeInChars(IntTy));
// Treat arrays as pointers, since that's how they're passed in.
else if (type->isArrayType())
- sz = getTypeSize(VoidPtrTy);
- return sz / getTypeSize(CharTy);
+ sz = getTypeSizeInChars(VoidPtrTy);
+ return sz;
+}
+
+static inline
+std::string charUnitsToString(const CharUnits &CU) {
+ return llvm::itostr(CU.getQuantity());
}
/// getObjCEncodingForBlockDecl - Return the encoded type for this method
@@ -3168,17 +3165,17 @@ void ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr,
// Start with computing size of a pointer in number of bytes.
// FIXME: There might(should) be a better way of doing this computation!
SourceLocation Loc;
- int PtrSize = getTypeSize(VoidPtrTy) / getTypeSize(CharTy);
- int ParmOffset = PtrSize;
+ CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy);
+ CharUnits ParmOffset = PtrSize;
for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(),
E = Decl->param_end(); PI != E; ++PI) {
QualType PType = (*PI)->getType();
- int sz = getObjCEncodingTypeSize(PType);
- assert (sz > 0 && "BlockExpr - Incomplete param type");
+ CharUnits sz = getObjCEncodingTypeSize(PType);
+ assert (sz.isPositive() && "BlockExpr - Incomplete param type");
ParmOffset += sz;
}
// Size of the argument frame
- S += llvm::utostr(ParmOffset);
+ S += charUnitsToString(ParmOffset);
// Block pointer and offset.
S += "@?0";
ParmOffset = PtrSize;
@@ -3198,7 +3195,7 @@ void ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr,
} else if (PType->isFunctionType())
PType = PVDecl->getType();
getObjCEncodingForType(PType, S);
- S += llvm::utostr(ParmOffset);
+ S += charUnitsToString(ParmOffset);
ParmOffset += getObjCEncodingTypeSize(PType);
}
}
@@ -3216,20 +3213,21 @@ void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
// Start with computing size of a pointer in number of bytes.
// FIXME: There might(should) be a better way of doing this computation!
SourceLocation Loc;
- int PtrSize = getTypeSize(VoidPtrTy) / getTypeSize(CharTy);
+ CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy);
// The first two arguments (self and _cmd) are pointers; account for
// their size.
- int ParmOffset = 2 * PtrSize;
+ CharUnits ParmOffset = 2 * PtrSize;
for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(),
E = Decl->param_end(); PI != E; ++PI) {
QualType PType = (*PI)->getType();
- int sz = getObjCEncodingTypeSize(PType);
- assert (sz > 0 && "getObjCEncodingForMethodDecl - Incomplete param type");
+ CharUnits sz = getObjCEncodingTypeSize(PType);
+ assert (sz.isPositive() &&
+ "getObjCEncodingForMethodDecl - Incomplete param type");
ParmOffset += sz;
}
- S += llvm::utostr(ParmOffset);
+ S += charUnitsToString(ParmOffset);
S += "@0:";
- S += llvm::utostr(PtrSize);
+ S += charUnitsToString(PtrSize);
// Argument types.
ParmOffset = 2 * PtrSize;
@@ -3249,7 +3247,7 @@ void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
// 'in', 'inout', etc.
getObjCEncodingForTypeQualifier(PVDecl->getObjCDeclQualifier(), S);
getObjCEncodingForType(PType, S);
- S += llvm::utostr(ParmOffset);
+ S += charUnitsToString(ParmOffset);
ParmOffset += getObjCEncodingTypeSize(PType);
}
}
diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp
new file mode 100644
index 0000000000000..02c70b651119a
--- /dev/null
+++ b/lib/AST/AttrImpl.cpp
@@ -0,0 +1,143 @@
+//===--- AttrImpl.cpp - Classes for representing attributes -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains out-of-line virtual methods for Attr classes.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "clang/AST/Attr.h"
+#include "clang/AST/ASTContext.h"
+using namespace clang;
+
+#define DEF_SIMPLE_ATTR_CLONE(ATTR) \
+ Attr *ATTR##Attr::clone(ASTContext &C) const { \
+ return ::new (C) ATTR##Attr; \
+ }
+
+// FIXME: Can we use variadic macro to define DEF_SIMPLE_ATTR_CLONE for
+// "non-simple" classes?
+
+DEF_SIMPLE_ATTR_CLONE(Packed)
+DEF_SIMPLE_ATTR_CLONE(AlwaysInline)
+DEF_SIMPLE_ATTR_CLONE(Malloc)
+DEF_SIMPLE_ATTR_CLONE(NoReturn)
+DEF_SIMPLE_ATTR_CLONE(AnalyzerNoReturn)
+DEF_SIMPLE_ATTR_CLONE(Deprecated)
+DEF_SIMPLE_ATTR_CLONE(Final)
+DEF_SIMPLE_ATTR_CLONE(Unavailable)
+DEF_SIMPLE_ATTR_CLONE(Unused)
+DEF_SIMPLE_ATTR_CLONE(Used)
+DEF_SIMPLE_ATTR_CLONE(Weak)
+DEF_SIMPLE_ATTR_CLONE(WeakImport)
+DEF_SIMPLE_ATTR_CLONE(NoThrow)
+DEF_SIMPLE_ATTR_CLONE(Const)
+DEF_SIMPLE_ATTR_CLONE(Pure)
+DEF_SIMPLE_ATTR_CLONE(FastCall)
+DEF_SIMPLE_ATTR_CLONE(StdCall)
+DEF_SIMPLE_ATTR_CLONE(CDecl)
+DEF_SIMPLE_ATTR_CLONE(TransparentUnion)
+DEF_SIMPLE_ATTR_CLONE(ObjCNSObject)
+DEF_SIMPLE_ATTR_CLONE(ObjCException)
+DEF_SIMPLE_ATTR_CLONE(NoDebug)
+DEF_SIMPLE_ATTR_CLONE(WarnUnusedResult)
+DEF_SIMPLE_ATTR_CLONE(NoInline)
+DEF_SIMPLE_ATTR_CLONE(CFReturnsRetained)
+DEF_SIMPLE_ATTR_CLONE(NSReturnsRetained)
+DEF_SIMPLE_ATTR_CLONE(BaseCheck)
+DEF_SIMPLE_ATTR_CLONE(Hiding)
+DEF_SIMPLE_ATTR_CLONE(Override)
+DEF_SIMPLE_ATTR_CLONE(DLLImport)
+DEF_SIMPLE_ATTR_CLONE(DLLExport)
+
+Attr* PragmaPackAttr::clone(ASTContext &C) const {
+ return ::new (C) PragmaPackAttr(Alignment);
+}
+
+Attr* AlignedAttr::clone(ASTContext &C) const {
+ return ::new (C) AlignedAttr(Alignment);
+}
+
+Attr* AnnotateAttr::clone(ASTContext &C) const {
+ return ::new (C) AnnotateAttr(Annotation);
+}
+
+Attr *AsmLabelAttr::clone(ASTContext &C) const {
+ return ::new (C) AsmLabelAttr(Label);
+}
+
+Attr *AliasAttr::clone(ASTContext &C) const {
+ return ::new (C) AliasAttr(Aliasee);
+}
+
+Attr *ConstructorAttr::clone(ASTContext &C) const {
+ return ::new (C) ConstructorAttr(priority);
+}
+
+Attr *DestructorAttr::clone(ASTContext &C) const {
+ return ::new (C) DestructorAttr(priority);
+}
+
+Attr *IBOutletAttr::clone(ASTContext &C) const {
+ return ::new (C) IBOutletAttr;
+}
+
+Attr *GNUInlineAttr::clone(ASTContext &C) const {
+ return ::new (C) GNUInlineAttr;
+}
+
+Attr *SectionAttr::clone(ASTContext &C) const {
+ return ::new (C) SectionAttr(Name);
+}
+
+Attr *NonNullAttr::clone(ASTContext &C) const {
+ return ::new (C) NonNullAttr(ArgNums, Size);
+}
+
+Attr *FormatAttr::clone(ASTContext &C) const {
+ return ::new (C) FormatAttr(Type, formatIdx, firstArg);
+}
+
+Attr *FormatArgAttr::clone(ASTContext &C) const {
+ return ::new (C) FormatArgAttr(formatIdx);
+}
+
+Attr *SentinelAttr::clone(ASTContext &C) const {
+ return ::new (C) SentinelAttr(sentinel, NullPos);
+}
+
+Attr *VisibilityAttr::clone(ASTContext &C) const {
+ return ::new (C) VisibilityAttr(VisibilityType);
+}
+
+Attr *OverloadableAttr::clone(ASTContext &C) const {
+ return ::new (C) OverloadableAttr;
+}
+
+Attr *BlocksAttr::clone(ASTContext &C) const {
+ return ::new (C) BlocksAttr(BlocksAttrType);
+}
+
+Attr *CleanupAttr::clone(ASTContext &C) const {
+ return ::new (C) CleanupAttr(FD);
+}
+
+Attr *RegparmAttr::clone(ASTContext &C) const {
+ return ::new (C) RegparmAttr(NumParams);
+}
+
+Attr *ReqdWorkGroupSizeAttr::clone(ASTContext &C) const {
+ return ::new (C) ReqdWorkGroupSizeAttr(X, Y, Z);
+}
+
+Attr *MSP430InterruptAttr::clone(ASTContext &C) const {
+ return ::new (C) MSP430InterruptAttr(Number);
+}
+
+
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 5aecf878c920b..dea96e7866ec1 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -4,6 +4,7 @@ add_clang_library(clangAST
APValue.cpp
ASTConsumer.cpp
ASTContext.cpp
+ AttrImpl.cpp
CXXInheritance.cpp
Decl.cpp
DeclBase.cpp
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index e112fa3928ded..e77661a9fbd4e 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -957,7 +957,7 @@ bool FunctionDecl::isInlined() const {
/// "externally" visible to other translation units in the program.
///
/// In C99, inline definitions are not externally visible by default. However,
-/// if even one of the globa-scope declarations is marked "extern inline", the
+/// if even one of the global-scope declarations is marked "extern inline", the
/// inline definition becomes externally visible (C99 6.7.4p6).
///
/// In GNU89 mode, or if the gnu_inline attribute is attached to the function
@@ -1039,6 +1039,15 @@ OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
return OO_None;
}
+/// getLiteralIdentifier - The literal suffix identifier this function
+/// represents, if any.
+const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const {
+ if (getDeclName().getNameKind() == DeclarationName::CXXLiteralOperatorName)
+ return getDeclName().getCXXLiteralIdentifier();
+ else
+ return 0;
+}
+
FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
if (MemberSpecializationInfo *Info = getMemberSpecializationInfo())
return cast(Info->getInstantiatedFrom());
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index bbbb19a35b4a8..1cce35c0b39a4 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -144,6 +144,19 @@ CXXRecordDecl::setBases(ASTContext &C,
}
}
+/// Callback function for CXXRecordDecl::forallBases that acknowledges
+/// that it saw a base class.
+static bool SawBase(const CXXRecordDecl *, void *) {
+ return true;
+}
+
+bool CXXRecordDecl::hasAnyDependentBases() const {
+ if (!isDependentContext())
+ return false;
+
+ return !forallBases(SawBase, 0);
+}
+
bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
return getCopyConstructor(Context, Qualifiers::Const) != 0;
}
@@ -643,23 +656,15 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const {
return C.getPointerType(ClassTy);
}
-static bool MethodHasBody(const CXXMethodDecl *MD, const FunctionDecl *&fn) {
- // Simple case: function has a body
- if (MD->getBody(fn))
- return true;
-
- // Complex case: function is an instantiation of a function which has a
- // body, but the definition hasn't been instantiated.
- const FunctionDecl *PatternDecl = MD->getTemplateInstantiationPattern();
- if (PatternDecl && PatternDecl->getBody(fn))
- return true;
-
- return false;
-}
-
bool CXXMethodDecl::hasInlineBody() const {
+ // If this function is a template instantiation, look at the template from
+ // which it was instantiated.
+ const FunctionDecl *CheckFn = getTemplateInstantiationPattern();
+ if (!CheckFn)
+ CheckFn = this;
+
const FunctionDecl *fn;
- return MethodHasBody(this, fn) && !fn->isOutOfLine();
+ return CheckFn->getBody(fn) && !fn->isOutOfLine();
}
CXXBaseOrMemberInitializer::
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 60c40e24fb31c..ff810735bc81d 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -56,9 +56,14 @@ public:
/// This identifier is stored here rather than directly in DeclarationName so as
/// to allow Objective-C selectors, which are about a million times more common,
/// to consume minimal memory.
-class CXXLiteralOperatorIdName : public DeclarationNameExtra {
+class CXXLiteralOperatorIdName
+ : public DeclarationNameExtra, public llvm::FoldingSetNode {
public:
IdentifierInfo *ID;
+
+ void Profile(llvm::FoldingSetNodeID &FSID) {
+ FSID.AddPointer(ID);
+ }
};
bool operator<(DeclarationName LHS, DeclarationName RHS) {
@@ -180,6 +185,11 @@ DeclarationName::NameKind DeclarationName::getNameKind() const {
return Identifier;
}
+bool DeclarationName::isDependentName() const {
+ QualType T = getCXXNameType();
+ return !T.isNull() && T->isDependentType();
+}
+
std::string DeclarationName::getAsString() const {
switch (getNameKind()) {
case Identifier:
@@ -353,6 +363,7 @@ void DeclarationName::dump() const {
DeclarationNameTable::DeclarationNameTable() {
CXXSpecialNamesImpl = new llvm::FoldingSet;
+ CXXLiteralOperatorNames = new llvm::FoldingSet;
// Initialize the overloaded operator names.
CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
@@ -364,16 +375,30 @@ DeclarationNameTable::DeclarationNameTable() {
}
DeclarationNameTable::~DeclarationNameTable() {
- llvm::FoldingSet *set =
+ llvm::FoldingSet *SpecialNames =
static_cast*>(CXXSpecialNamesImpl);
- llvm::FoldingSetIterator I = set->begin(), E = set->end();
+ llvm::FoldingSetIterator
+ SI = SpecialNames->begin(), SE = SpecialNames->end();
+
+ while (SI != SE) {
+ CXXSpecialName *n = &*SI++;
+ delete n;
+ }
- while (I != E) {
- CXXSpecialName *n = &*I++;
+
+ llvm::FoldingSet *LiteralNames
+ = static_cast*>
+ (CXXLiteralOperatorNames);
+ llvm::FoldingSetIterator
+ LI = LiteralNames->begin(), LE = LiteralNames->end();
+
+ while (LI != LE) {
+ CXXLiteralOperatorIdName *n = &*LI++;
delete n;
}
- delete set;
+ delete SpecialNames;
+ delete LiteralNames;
delete [] CXXOperatorNames;
}
@@ -428,9 +453,23 @@ DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
DeclarationName
DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
+ llvm::FoldingSet *LiteralNames
+ = static_cast*>
+ (CXXLiteralOperatorNames);
+
+ llvm::FoldingSetNodeID ID;
+ ID.AddPointer(II);
+
+ void *InsertPos = 0;
+ if (CXXLiteralOperatorIdName *Name =
+ LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
+ return DeclarationName (Name);
+
CXXLiteralOperatorIdName *LiteralName = new CXXLiteralOperatorIdName;
LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
LiteralName->ID = II;
+
+ LiteralNames->InsertNode(LiteralName, InsertPos);
return DeclarationName(LiteralName);
}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 04a6abca87c96..4c3046bed10bb 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -2154,7 +2154,8 @@ IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() {
return getField()->getIdentifier();
}
-DesignatedInitExpr::DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
+DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty,
+ unsigned NumDesignators,
const Designator *Designators,
SourceLocation EqualOrColonLoc,
bool GNUSyntax,
@@ -2165,7 +2166,7 @@ DesignatedInitExpr::DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
Init->isTypeDependent(), Init->isValueDependent()),
EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax),
NumDesignators(NumDesignators), NumSubExprs(NumIndexExprs + 1) {
- this->Designators = new Designator[NumDesignators];
+ this->Designators = new (C) Designator[NumDesignators];
// Record the initializer itself.
child_iterator Child = child_begin();
@@ -2210,7 +2211,7 @@ DesignatedInitExpr::Create(ASTContext &C, Designator *Designators,
bool UsesColonSyntax, Expr *Init) {
void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
sizeof(Stmt *) * (NumIndexExprs + 1), 8);
- return new (Mem) DesignatedInitExpr(C.VoidTy, NumDesignators, Designators,
+ return new (Mem) DesignatedInitExpr(C, C.VoidTy, NumDesignators, Designators,
ColonOrEqualLoc, UsesColonSyntax,
IndexExprs, NumIndexExprs, Init);
}
@@ -2222,12 +2223,12 @@ DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(ASTContext &C,
return new (Mem) DesignatedInitExpr(NumIndexExprs + 1);
}
-void DesignatedInitExpr::setDesignators(const Designator *Desigs,
+void DesignatedInitExpr::setDesignators(ASTContext &C,
+ const Designator *Desigs,
unsigned NumDesigs) {
- if (Designators)
- delete [] Designators;
+ DestroyDesignators(C);
- Designators = new Designator[NumDesigs];
+ Designators = new (C) Designator[NumDesigs];
NumDesignators = NumDesigs;
for (unsigned I = 0; I != NumDesigs; ++I)
Designators[I] = Desigs[I];
@@ -2276,7 +2277,7 @@ Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator& D) {
/// \brief Replaces the designator at index @p Idx with the series
/// of designators in [First, Last).
-void DesignatedInitExpr::ExpandDesignator(unsigned Idx,
+void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx,
const Designator *First,
const Designator *Last) {
unsigned NumNewDesignators = Last - First;
@@ -2292,21 +2293,28 @@ void DesignatedInitExpr::ExpandDesignator(unsigned Idx,
}
Designator *NewDesignators
- = new Designator[NumDesignators - 1 + NumNewDesignators];
+ = new (C) Designator[NumDesignators - 1 + NumNewDesignators];
std::copy(Designators, Designators + Idx, NewDesignators);
std::copy(First, Last, NewDesignators + Idx);
std::copy(Designators + Idx + 1, Designators + NumDesignators,
NewDesignators + Idx + NumNewDesignators);
- delete [] Designators;
+ DestroyDesignators(C);
Designators = NewDesignators;
NumDesignators = NumDesignators - 1 + NumNewDesignators;
}
void DesignatedInitExpr::DoDestroy(ASTContext &C) {
- delete [] Designators;
+ DestroyDesignators(C);
Expr::DoDestroy(C);
}
+void DesignatedInitExpr::DestroyDesignators(ASTContext &C) {
+ for (unsigned I = 0; I != NumDesignators; ++I)
+ Designators[I].~Designator();
+ C.Deallocate(Designators);
+ Designators = 0;
+}
+
ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
Expr **exprs, unsigned nexprs,
SourceLocation rparenloc)
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 06afec7675f12..dfff2099cbd6d 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -13,6 +13,7 @@
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/ASTDiagnostic.h"
@@ -69,11 +70,12 @@ static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info);
static bool EvalPointerValueAsBool(APValue& Value, bool& Result) {
// FIXME: Is this accurate for all kinds of bases? If not, what would
// the check look like?
- Result = Value.getLValueBase() || Value.getLValueOffset();
+ Result = Value.getLValueBase() || !Value.getLValueOffset().isZero();
return true;
}
-static bool HandleConversionToBool(Expr* E, bool& Result, EvalInfo &Info) {
+static bool HandleConversionToBool(const Expr* E, bool& Result,
+ EvalInfo &Info) {
if (E->getType()->isIntegralType()) {
APSInt IntResult;
if (!EvaluateInteger(E, IntResult, Info))
@@ -222,11 +224,11 @@ public:
APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
APValue VisitDeclRefExpr(DeclRefExpr *E);
- APValue VisitPredefinedExpr(PredefinedExpr *E) { return APValue(E, 0); }
+ APValue VisitPredefinedExpr(PredefinedExpr *E) { return APValue(E); }
APValue VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
APValue VisitMemberExpr(MemberExpr *E);
- APValue VisitStringLiteral(StringLiteral *E) { return APValue(E, 0); }
- APValue VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return APValue(E, 0); }
+ APValue VisitStringLiteral(StringLiteral *E) { return APValue(E); }
+ APValue VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return APValue(E); }
APValue VisitArraySubscriptExpr(ArraySubscriptExpr *E);
APValue VisitUnaryDeref(UnaryOperator *E);
APValue VisitUnaryExtension(const UnaryOperator *E)
@@ -254,12 +256,12 @@ static bool EvaluateLValue(const Expr* E, APValue& Result, EvalInfo &Info) {
APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
if (isa(E->getDecl())) {
- return APValue(E, 0);
+ return APValue(E);
} else if (VarDecl* VD = dyn_cast(E->getDecl())) {
if (!Info.AnyLValue && !VD->hasGlobalStorage())
return APValue();
if (!VD->getType()->isReferenceType())
- return APValue(E, 0);
+ return APValue(E);
// FIXME: Check whether VD might be overridden!
const VarDecl *Def = 0;
if (const Expr *Init = VD->getDefinition(Def))
@@ -272,7 +274,7 @@ APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
APValue LValueExprEvaluator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
if (!Info.AnyLValue && !E->isFileScope())
return APValue();
- return APValue(E, 0);
+ return APValue(E);
}
APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
@@ -309,7 +311,8 @@ APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
}
result.setLValue(result.getLValueBase(),
- result.getLValueOffset() + RL.getFieldOffset(i) / 8);
+ result.getLValueOffset() +
+ CharUnits::fromQuantity(RL.getFieldOffset(i) / 8));
return result;
}
@@ -324,9 +327,9 @@ APValue LValueExprEvaluator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
if (!EvaluateInteger(E->getIdx(), Index, Info))
return APValue();
- uint64_t ElementSize = Info.Ctx.getTypeSize(E->getType()) / 8;
+ CharUnits ElementSize = Info.Ctx.getTypeSizeInChars(E->getType());
- uint64_t Offset = Index.getSExtValue() * ElementSize;
+ CharUnits Offset = Index.getSExtValue() * ElementSize;
Result.setLValue(Result.getLValueBase(),
Result.getLValueOffset() + Offset);
return Result;
@@ -363,22 +366,22 @@ public:
{ return Visit(E->getSubExpr()); }
APValue VisitUnaryAddrOf(const UnaryOperator *E);
APValue VisitObjCStringLiteral(ObjCStringLiteral *E)
- { return APValue(E, 0); }
+ { return APValue(E); }
APValue VisitAddrLabelExpr(AddrLabelExpr *E)
- { return APValue(E, 0); }
+ { return APValue(E); }
APValue VisitCallExpr(CallExpr *E);
APValue VisitBlockExpr(BlockExpr *E) {
if (!E->hasBlockDeclRefExprs())
- return APValue(E, 0);
+ return APValue(E);
return APValue();
}
APValue VisitImplicitValueInitExpr(ImplicitValueInitExpr *E)
- { return APValue((Expr*)0, 0); }
+ { return APValue((Expr*)0); }
APValue VisitConditionalOperator(ConditionalOperator *E);
APValue VisitChooseExpr(ChooseExpr *E)
{ return Visit(E->getChosenSubExpr(Info.Ctx)); }
APValue VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E)
- { return APValue((Expr*)0, 0); }
+ { return APValue((Expr*)0); }
// FIXME: Missing: @protocol, @selector
};
} // end anonymous namespace
@@ -409,15 +412,15 @@ APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
return APValue();
QualType PointeeType = PExp->getType()->getAs()->getPointeeType();
- uint64_t SizeOfPointee;
+ CharUnits SizeOfPointee;
// Explicitly handle GNU void* and function pointer arithmetic extensions.
if (PointeeType->isVoidType() || PointeeType->isFunctionType())
- SizeOfPointee = 1;
+ SizeOfPointee = CharUnits::One();
else
- SizeOfPointee = Info.Ctx.getTypeSize(PointeeType) / 8;
+ SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType);
- uint64_t Offset = ResultLValue.getLValueOffset();
+ CharUnits Offset = ResultLValue.getLValueOffset();
if (E->getOpcode() == BinaryOperator::Add)
Offset += AdditionalOffset.getLimitedValue() * SizeOfPointee;
@@ -459,7 +462,8 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
if (Result.isInt()) {
Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
- return APValue(0, Result.getInt().getZExtValue());
+ return APValue(0,
+ CharUnits::fromQuantity(Result.getInt().getZExtValue()));
}
// Cast is of an lvalue, no need to change value.
@@ -481,7 +485,8 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
if (Result.isInt()) {
Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
- return APValue(0, Result.getInt().getZExtValue());
+ return APValue(0,
+ CharUnits::fromQuantity(Result.getInt().getZExtValue()));
}
// Cast is of an lvalue, no need to change value.
@@ -502,7 +507,7 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
APValue PointerExprEvaluator::VisitCallExpr(CallExpr *E) {
if (E->isBuiltinCall(Info.Ctx) ==
Builtin::BI__builtin___CFStringMakeConstantString)
- return APValue(E, 0);
+ return APValue(E);
return APValue();
}
@@ -976,20 +981,20 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
&& VD->getType()->isObjectType()
&& !VD->getType()->isVariablyModifiedType()
&& !VD->getType()->isDependentType()) {
- uint64_t Size = Info.Ctx.getTypeSize(VD->getType()) / 8;
- uint64_t Offset = Base.Val.getLValueOffset();
- if (Offset <= Size)
- Size -= Base.Val.getLValueOffset();
+ CharUnits Size = Info.Ctx.getTypeSizeInChars(VD->getType());
+ CharUnits Offset = Base.Val.getLValueOffset();
+ if (!Offset.isNegative() && Offset <= Size)
+ Size -= Offset;
else
- Size = 0;
- return Success(Size, E);
+ Size = CharUnits::Zero();
+ return Success(Size.getQuantity(), E);
}
}
}
// TODO: Perhaps we should let LLVM lower this?
if (E->getArg(0)->HasSideEffects(Info.Ctx)) {
- if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() == 0)
+ if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() <= 1)
return Success(-1ULL, E);
return Success(0, E);
}
@@ -1151,7 +1156,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (LHSValue.getLValueBase()) {
if (!E->isEqualityOp())
return false;
- if (RHSValue.getLValueBase() || RHSValue.getLValueOffset())
+ if (RHSValue.getLValueBase() || !RHSValue.getLValueOffset().isZero())
return false;
bool bres;
if (!EvalPointerValueAsBool(LHSValue, bres))
@@ -1160,7 +1165,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
} else if (RHSValue.getLValueBase()) {
if (!E->isEqualityOp())
return false;
- if (LHSValue.getLValueBase() || LHSValue.getLValueOffset())
+ if (LHSValue.getLValueBase() || !LHSValue.getLValueOffset().isZero())
return false;
bool bres;
if (!EvalPointerValueAsBool(RHSValue, bres))
@@ -1172,11 +1177,13 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
const QualType Type = E->getLHS()->getType();
const QualType ElementType = Type->getAs()->getPointeeType();
- uint64_t D = LHSValue.getLValueOffset() - RHSValue.getLValueOffset();
+ CharUnits ElementSize = CharUnits::One();
if (!ElementType->isVoidType() && !ElementType->isFunctionType())
- D /= Info.Ctx.getTypeSize(ElementType) / 8;
+ ElementSize = Info.Ctx.getTypeSizeInChars(ElementType);
- return Success(D, E);
+ CharUnits Diff = LHSValue.getLValueOffset() -
+ RHSValue.getLValueOffset();
+ return Success(Diff / ElementSize, E);
}
bool Result;
if (E->getOpcode() == BinaryOperator::EQ) {
@@ -1204,21 +1211,23 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
// Handle cases like (unsigned long)&a + 4.
if (E->isAdditiveOp() && Result.isLValue() && RHSVal.isInt()) {
- uint64_t offset = Result.getLValueOffset();
+ CharUnits Offset = Result.getLValueOffset();
+ CharUnits AdditionalOffset = CharUnits::fromQuantity(
+ RHSVal.getInt().getZExtValue());
if (E->getOpcode() == BinaryOperator::Add)
- offset += RHSVal.getInt().getZExtValue();
+ Offset += AdditionalOffset;
else
- offset -= RHSVal.getInt().getZExtValue();
- Result = APValue(Result.getLValueBase(), offset);
+ Offset -= AdditionalOffset;
+ Result = APValue(Result.getLValueBase(), Offset);
return true;
}
// Handle cases like 4 + (unsigned long)&a
if (E->getOpcode() == BinaryOperator::Add &&
RHSVal.isLValue() && Result.isInt()) {
- uint64_t offset = RHSVal.getLValueOffset();
- offset += Result.getInt().getZExtValue();
- Result = APValue(RHSVal.getLValueBase(), offset);
+ CharUnits Offset = RHSVal.getLValueOffset();
+ Offset += CharUnits::fromQuantity(Result.getInt().getZExtValue());
+ Result = APValue(RHSVal.getLValueBase(), Offset);
return true;
}
@@ -1334,8 +1343,7 @@ bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
return false;
// Get information about the size.
- unsigned BitWidth = Info.Ctx.getTypeSize(SrcTy);
- return Success(BitWidth / Info.Ctx.Target.getCharWidth(), E);
+ return Success(Info.Ctx.getTypeSizeInChars(SrcTy).getQuantity(), E);
}
bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
@@ -1349,7 +1357,7 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
return false;
if (LV.getLValueBase())
return false;
- return Success(LV.getLValueOffset(), E);
+ return Success(LV.getLValueOffset().getQuantity(), E);
}
if (E->getOpcode() == UnaryOperator::LNot) {
@@ -1432,7 +1440,8 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) {
return true;
}
- APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset(), SrcType);
+ APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset().getQuantity(),
+ SrcType);
return Success(HandleIntToIntCast(DestType, SrcType, AsInt, Info.Ctx), E);
}
@@ -1978,6 +1987,13 @@ bool Expr::EvaluateAsAny(EvalResult &Result, ASTContext &Ctx) const {
return true;
}
+bool Expr::EvaluateAsBooleanCondition(bool &Result, ASTContext &Ctx) const {
+ EvalResult Scratch;
+ EvalInfo Info(Ctx, Scratch);
+
+ return HandleConversionToBool(this, Result, Info);
+}
+
bool Expr::EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const {
EvalInfo Info(Ctx, Result);
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index c914f3f82e8e0..cfd89eaed3507 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -719,11 +719,6 @@ ASTRecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) {
// If a class isnt' polymorphic it doesn't have a key function.
if (!RD->isPolymorphic())
return 0;
-
- // A class template specialization or instantation does not have a key
- // function.
- if (RD->getTemplateSpecializationKind() != TSK_Undeclared)
- return 0;
// A class inside an anonymous namespace doesn't have a key function. (Or
// at least, there's no point to assigning a key function to such a class;
@@ -741,13 +736,13 @@ ASTRecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) {
if (MD->isPure())
continue;
- if (MD->isInlineSpecified())
- continue;
-
// Ignore implicit member functions, they are always marked as inline, but
// they don't have a body until they're defined.
if (MD->isImplicit())
continue;
+
+ if (MD->isInlineSpecified())
+ continue;
if (MD->hasInlineBody())
continue;
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 7c7aeb8d3e1df..104e3361892f0 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -337,12 +337,12 @@ unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl&Pieces,
//===----------------------------------------------------------------------===//
AsmStmt::AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile,
- unsigned numoutputs, unsigned numinputs,
+ bool msasm, unsigned numoutputs, unsigned numinputs,
std::string *names, StringLiteral **constraints,
Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
StringLiteral **clobbers, SourceLocation rparenloc)
: Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr)
- , IsSimple(issimple), IsVolatile(isvolatile)
+ , IsSimple(issimple), IsVolatile(isvolatile), MSAsm(msasm)
, NumOutputs(numoutputs), NumInputs(numinputs) {
for (unsigned i = 0, e = numinputs + numoutputs; i != e; i++) {
Names.push_back(names[i]);
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index a7e42af04d81b..bbb904de79b32 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -739,9 +739,10 @@ void StmtPrinter::VisitCallExpr(CallExpr *Call) {
void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
// FIXME: Suppress printing implicit bases (like "this")
PrintExpr(Node->getBase());
+ if (FieldDecl *FD = dyn_cast(Node->getMemberDecl()))
+ if (FD->isAnonymousStructOrUnion())
+ return;
OS << (Node->isArrow() ? "->" : ".");
- // FIXME: Suppress printing references to unnamed objects
- // representing anonymous unions/structs
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
Qualifier->print(OS, Policy);
@@ -1120,6 +1121,13 @@ void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
}
void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) {
+ // FIXME. For now we just print a trivial constructor call expression,
+ // constructing its first argument object.
+ if (E->getNumArgs() == 1) {
+ CXXConstructorDecl *CD = E->getConstructor();
+ if (CD->isTrivial())
+ PrintExpr(E->getArg(0));
+ }
// Nothing to print.
}
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 3ccb7a9cc613c..0840c52b4c202 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -13,6 +13,7 @@
#include "llvm/Support/raw_ostream.h"
#include "clang/AST/TypeLocVisitor.h"
+#include "clang/AST/Expr.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -123,3 +124,14 @@ bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
if (TL->getType().hasLocalQualifiers()) return false;
return TSTChecker().Visit(*TL);
}
+
+// Reimplemented to account for GNU/C++ extension
+// typeof unary-expression
+// where there are no parentheses.
+SourceRange TypeOfExprTypeLoc::getSourceRange() const {
+ if (getRParenLoc().isValid())
+ return SourceRange(getTypeofLoc(), getRParenLoc());
+ else
+ return SourceRange(getTypeofLoc(),
+ getUnderlyingExpr()->getSourceRange().getEnd());
+}
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 818657c2a7634..00b74bc21a14a 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -271,6 +271,10 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
S += ")";
+ if (T->getNoReturnAttr())
+ S += " __attribute__((noreturn))";
+
+
if (T->hasExceptionSpec()) {
S += " throw(";
if (T->hasAnyExceptionSpec())
@@ -287,10 +291,9 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
S += ")";
}
- if (T->getNoReturnAttr())
- S += " __attribute__((noreturn))";
- Print(T->getResultType(), S);
+ AppendTypeQualList(S, T->getTypeQuals());
+ Print(T->getResultType(), S);
}
void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T,
diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp
index 97e6d914d450f..2093b5e23e852 100644
--- a/lib/Analysis/AnalysisContext.cpp
+++ b/lib/Analysis/AnalysisContext.cpp
@@ -18,6 +18,7 @@
#include "clang/Analysis/CFG.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Support/BumpVector.h"
@@ -38,6 +39,9 @@ Stmt *AnalysisContext::getBody() {
return MD->getBody();
else if (const BlockDecl *BD = dyn_cast(D))
return BD->getBody();
+ else if (const FunctionTemplateDecl *FunTmpl
+ = dyn_cast_or_null(D))
+ return FunTmpl->getTemplatedDecl()->getBody();
llvm_unreachable("unknown code decl");
}
diff --git a/lib/Analysis/BasicConstraintManager.cpp b/lib/Analysis/BasicConstraintManager.cpp
index 6c3f7b2245df0..6dfc470530a4e 100644
--- a/lib/Analysis/BasicConstraintManager.cpp
+++ b/lib/Analysis/BasicConstraintManager.cpp
@@ -49,8 +49,9 @@ class BasicConstraintManager
: public SimpleConstraintManager {
GRState::IntSetTy::Factory ISetFactory;
public:
- BasicConstraintManager(GRStateManager& statemgr)
- : ISetFactory(statemgr.getAllocator()) {}
+ BasicConstraintManager(GRStateManager &statemgr, GRSubEngine &subengine)
+ : SimpleConstraintManager(subengine),
+ ISetFactory(statemgr.getAllocator()) {}
const GRState* AssumeSymNE(const GRState* state, SymbolRef sym,
const llvm::APSInt& V);
@@ -88,9 +89,9 @@ public:
} // end anonymous namespace
-ConstraintManager* clang::CreateBasicConstraintManager(GRStateManager& StateMgr)
-{
- return new BasicConstraintManager(StateMgr);
+ConstraintManager* clang::CreateBasicConstraintManager(GRStateManager& statemgr,
+ GRSubEngine &subengine) {
+ return new BasicConstraintManager(statemgr, subengine);
}
const GRState*
diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp
index e6482698dd43d..2a9531df60f18 100644
--- a/lib/Analysis/BugReporter.cpp
+++ b/lib/Analysis/BugReporter.cpp
@@ -1818,8 +1818,23 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) {
R->getRanges(Beg, End);
Diagnostic& Diag = getDiagnostic();
FullSourceLoc L(R->getLocation(), getSourceManager());
- unsigned ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning,
- R->getShortDescription().c_str());
+
+ // Search the description for '%', as that will be interpretted as a
+ // format character by FormatDiagnostics.
+ llvm::StringRef desc = R->getShortDescription();
+ unsigned ErrorDiag;
+ {
+ llvm::SmallString<512> TmpStr;
+ llvm::raw_svector_ostream Out(TmpStr);
+ for (llvm::StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I)
+ if (*I == '%')
+ Out << "%%";
+ else
+ Out << *I;
+
+ Out.flush();
+ ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, TmpStr);
+ }
switch (End-Beg) {
default: assert(0 && "Don't handle this many ranges yet!");
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index a15a8f16c46f1..5a15fbfb1f05f 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -52,8 +52,8 @@ using namespace clang;
// not release it."
//
-using llvm::CStrInCStrNoCase;
-using llvm::StringsEqualNoCase;
+using llvm::StrInStrNoCase;
+using llvm::StringRef;
enum NamingConvention { NoConvention, CreateRule, InitRule };
@@ -122,20 +122,20 @@ static NamingConvention deriveNamingConvention(Selector S) {
break;
case 3:
// Methods starting with 'new' follow the create rule.
- if (AtBeginning && StringsEqualNoCase("new", s, len))
+ if (AtBeginning && StringRef(s, len).equals_lower("new"))
C = CreateRule;
break;
case 4:
// Methods starting with 'alloc' or contain 'copy' follow the
// create rule
- if (C == NoConvention && StringsEqualNoCase("copy", s, len))
+ if (C == NoConvention && StringRef(s, len).equals_lower("copy"))
C = CreateRule;
else // Methods starting with 'init' follow the init rule.
- if (AtBeginning && StringsEqualNoCase("init", s, len))
+ if (AtBeginning && StringRef(s, len).equals_lower("init"))
C = InitRule;
break;
case 5:
- if (AtBeginning && StringsEqualNoCase("alloc", s, len))
+ if (AtBeginning && StringRef(s, len).equals_lower("alloc"))
C = CreateRule;
break;
}
@@ -1372,11 +1372,11 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// "AppendValue", or "SetAttribute", then we assume that arguments may
// "escape." This means that something else holds on to the object,
// allowing it be used even after its local retain count drops to 0.
- ArgEffect E = (CStrInCStrNoCase(FName, "InsertValue") ||
- CStrInCStrNoCase(FName, "AddValue") ||
- CStrInCStrNoCase(FName, "SetValue") ||
- CStrInCStrNoCase(FName, "AppendValue") ||
- CStrInCStrNoCase(FName, "SetAttribute"))
+ ArgEffect E = (StrInStrNoCase(FName, "InsertValue") != StringRef::npos||
+ StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
+ StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
+ StrInStrNoCase(FName, "AppendValue") != StringRef::npos||
+ StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
? MayEscape : DoNothing;
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, E);
@@ -1555,7 +1555,8 @@ RetainSummaryManager::getCommonMethodSummary(const ObjCMethodDecl* MD,
if (S.isKeywordSelector()) {
const std::string &str = S.getAsString();
assert(!str.empty());
- if (CStrInCStrNoCase(&str[0], "delegate:")) ReceiverEff = StopTracking;
+ if (StrInStrNoCase(str, "delegate:") != StringRef::npos)
+ ReceiverEff = StopTracking;
}
// Look for methods that return an owned object.
diff --git a/lib/Analysis/CheckSecuritySyntaxOnly.cpp b/lib/Analysis/CheckSecuritySyntaxOnly.cpp
index 3214101c6485a..f4874a5dfe4cd 100644
--- a/lib/Analysis/CheckSecuritySyntaxOnly.cpp
+++ b/lib/Analysis/CheckSecuritySyntaxOnly.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/TargetInfo.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/LocalCheckers.h"
#include "clang/AST/StmtVisitor.h"
@@ -18,6 +19,12 @@
using namespace clang;
+static bool isArc4RandomAvailable(const ASTContext &Ctx) {
+ const llvm::Triple &T = Ctx.Target.getTriple();
+ return T.getVendor() == llvm::Triple::Apple ||
+ T.getOS() == llvm::Triple::FreeBSD;
+}
+
namespace {
class WalkAST : public StmtVisitor {
BugReporter &BR;
@@ -29,11 +36,14 @@ class WalkAST : public StmtVisitor {
IdentifierInfo *II_random;
enum { num_setids = 6 };
IdentifierInfo *II_setid[num_setids];
+
+ const bool CheckRand;
public:
WalkAST(BugReporter &br) : BR(br),
II_gets(0), II_getpw(0), II_mktemp(0),
- II_rand(), II_random(0), II_setid() {}
+ II_rand(), II_random(0), II_setid(),
+ CheckRand(isArc4RandomAvailable(BR.getContext())) {}
// Statement visitor methods.
void VisitCallExpr(CallExpr *CE);
@@ -83,8 +93,10 @@ void WalkAST::VisitCallExpr(CallExpr *CE) {
CheckCall_gets(CE, FD);
CheckCall_getpw(CE, FD);
CheckCall_mktemp(CE, FD);
- CheckCall_rand(CE, FD);
- CheckCall_random(CE, FD);
+ if (CheckRand) {
+ CheckCall_rand(CE, FD);
+ CheckCall_random(CE, FD);
+ }
}
// Recurse and check children.
diff --git a/lib/Analysis/Environment.cpp b/lib/Analysis/Environment.cpp
index dd2f08b48f76d..f04cf7b05fed5 100644
--- a/lib/Analysis/Environment.cpp
+++ b/lib/Analysis/Environment.cpp
@@ -37,7 +37,12 @@ SVal Environment::GetSVal(const Stmt *E, ValueManager& ValMgr) const {
}
case Stmt::IntegerLiteralClass: {
- return ValMgr.makeIntVal(cast(E));
+ // In C++, this expression may have been bound to a temporary object.
+ SVal const *X = ExprBindings.lookup(E);
+ if (X)
+ return *X;
+ else
+ return ValMgr.makeIntVal(cast(E));
}
// Casts where the source and target type are the same
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 2ce8edd1cc466..40c12c9fec84f 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -17,6 +17,7 @@
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "clang/Analysis/PathSensitive/GRExprEngineBuilders.h"
#include "clang/Analysis/PathSensitive/Checker.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Basic/Builtins.h"
@@ -47,10 +48,9 @@ static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
}
-static bool CalleeReturnsReference(const CallExpr *CE) {
+static QualType GetCalleeReturnType(const CallExpr *CE) {
const Expr *Callee = CE->getCallee();
QualType T = Callee->getType();
-
if (const PointerType *PT = T->getAs()) {
const FunctionType *FT = PT->getPointeeType()->getAs();
T = FT->getResultType();
@@ -58,16 +58,35 @@ static bool CalleeReturnsReference(const CallExpr *CE) {
else {
const BlockPointerType *BT = T->getAs();
T = BT->getPointeeType()->getAs()->getResultType();
- }
- return T->isReferenceType();
+ }
+ return T;
+}
+
+static bool CalleeReturnsReference(const CallExpr *CE) {
+ return (bool) GetCalleeReturnType(CE)->getAs();
}
static bool ReceiverReturnsReference(const ObjCMessageExpr *ME) {
const ObjCMethodDecl *MD = ME->getMethodDecl();
if (!MD)
return false;
- return MD->getResultType()->isReferenceType();
+ return MD->getResultType()->getAs();
+}
+
+#ifndef NDEBUG
+static bool ReceiverReturnsReferenceOrRecord(const ObjCMessageExpr *ME) {
+ const ObjCMethodDecl *MD = ME->getMethodDecl();
+ if (!MD)
+ return false;
+ QualType T = MD->getResultType();
+ return T->getAs() || T->getAs();
+}
+
+static bool CalleeReturnsReferenceOrRecord(const CallExpr *CE) {
+ QualType T = GetCalleeReturnType(CE);
+ return T->getAs() || T->getAs();
}
+#endif
//===----------------------------------------------------------------------===//
// Batch auditor. DEPRECATED.
@@ -300,23 +319,27 @@ static void RegisterInternalChecks(GRExprEngine &Eng) {
RegisterOSAtomicChecker(Eng);
}
-GRExprEngine::GRExprEngine(AnalysisManager &mgr)
+GRExprEngine::GRExprEngine(AnalysisManager &mgr, GRTransferFuncs *tf)
: AMgr(mgr),
CoreEngine(mgr.getASTContext(), *this),
G(CoreEngine.getGraph()),
Builder(NULL),
StateMgr(G.getContext(), mgr.getStoreManagerCreator(),
- mgr.getConstraintManagerCreator(), G.getAllocator()),
+ mgr.getConstraintManagerCreator(), G.getAllocator(),
+ *this),
SymMgr(StateMgr.getSymbolManager()),
ValMgr(StateMgr.getValueManager()),
SVator(ValMgr.getSValuator()),
CurrentStmt(NULL),
NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL),
RaiseSel(GetNullarySelector("raise", G.getContext())),
- BR(mgr, *this)
-{
+ BR(mgr, *this), TF(tf) {
// Register internal checks.
RegisterInternalChecks(*this);
+
+ // FIXME: Eventually remove the TF object entirely.
+ TF->RegisterChecks(*this);
+ TF->RegisterPrinters(getStateManager().Printers);
}
GRExprEngine::~GRExprEngine() {
@@ -330,13 +353,6 @@ GRExprEngine::~GRExprEngine() {
// Utility methods.
//===----------------------------------------------------------------------===//
-void GRExprEngine::setTransferFunctionsAndCheckers(GRTransferFuncs* tf) {
- StateMgr.TF = tf;
- StateMgr.Checkers = &Checkers;
- tf->RegisterChecks(*this);
- tf->RegisterPrinters(getStateManager().Printers);
-}
-
void GRExprEngine::AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C) {
if (!BatchAuditor)
BatchAuditor.reset(new MappedBatchAuditor(getGraph().getAllocator()));
@@ -415,6 +431,25 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) {
// Top-level transfer function logic (Dispatcher).
//===----------------------------------------------------------------------===//
+/// EvalAssume - Called by ConstraintManager. Used to call checker-specific
+/// logic for handling assumptions on symbolic values.
+const GRState *GRExprEngine::ProcessAssume(const GRState *state, SVal cond,
+ bool assumption) {
+ for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
+ I != E; ++I) {
+
+ if (!state)
+ return NULL;
+
+ state = I->second->EvalAssume(state, cond, assumption);
+ }
+
+ if (!state)
+ return NULL;
+
+ return TF->EvalAssume(state, cond, assumption);
+}
+
void GRExprEngine::ProcessStmt(CFGElement CE, GRStmtNodeBuilder& builder) {
CurrentStmt = CE.getStmt();
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
@@ -809,7 +844,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
case Stmt::CallExprClass:
case Stmt::CXXOperatorCallExprClass: {
CallExpr *C = cast(Ex);
- assert(CalleeReturnsReference(C));
+ assert(CalleeReturnsReferenceOrRecord(C));
VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, true);
break;
}
@@ -840,7 +875,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
case Stmt::ObjCMessageExprClass: {
ObjCMessageExpr *ME = cast(Ex);
- assert(ReceiverReturnsReference(ME));
+ assert(ReceiverReturnsReferenceOrRecord(ME));
VisitObjCMessageExpr(ME, Pred, Dst, true);
return;
}
@@ -871,6 +906,11 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
case Stmt::UnaryOperatorClass:
VisitUnaryOperator(cast(Ex), Pred, Dst, true);
return;
+
+ // In C++, binding an rvalue to a reference requires to create an object.
+ case Stmt::IntegerLiteralClass:
+ CreateCXXTemporaryObject(Ex, Pred, Dst);
+ return;
default:
// Arbitrary subexpressions can return aggregate temporaries that
@@ -1205,7 +1245,8 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
do {
nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt()));
- DefinedOrUnknownSVal Res = SVator.EvalEQ(DefaultSt, CondV, CaseVal);
+ DefinedOrUnknownSVal Res = SVator.EvalEQ(DefaultSt ? DefaultSt : state,
+ CondV, CaseVal);
// Now "assume" that the case matches.
if (const GRState* stateNew = state->Assume(Res, true)) {
@@ -1220,11 +1261,17 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
// Now "assume" that the case doesn't match. Add this state
// to the default state (if it is feasible).
- if (const GRState *stateNew = DefaultSt->Assume(Res, false)) {
- defaultIsFeasible = true;
- DefaultSt = stateNew;
+ if (DefaultSt) {
+ if (const GRState *stateNew = DefaultSt->Assume(Res, false)) {
+ defaultIsFeasible = true;
+ DefaultSt = stateNew;
+ }
+ else {
+ defaultIsFeasible = false;
+ DefaultSt = NULL;
+ }
}
-
+
// Concretize the next value in the range.
if (V1.Val.getInt() == V2.Val.getInt())
break;
@@ -2375,12 +2422,12 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
ExplodedNode* Pred,
ExplodedNodeSet& Dst) {
QualType T = Ex->getTypeOfArgument();
- uint64_t amt;
+ CharUnits amt;
if (Ex->isSizeOf()) {
if (T == getContext().VoidTy) {
// sizeof(void) == 1 byte.
- amt = 1;
+ amt = CharUnits::One();
}
else if (!T.getTypePtr()->isConstantSizeType()) {
// FIXME: Add support for VLAs.
@@ -2394,14 +2441,15 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
}
else {
// All other cases.
- amt = getContext().getTypeSize(T) / 8;
+ amt = getContext().getTypeSizeInChars(T);
}
}
else // Get alignment of the type.
- amt = getContext().getTypeAlign(T) / 8;
+ amt = CharUnits::fromQuantity(getContext().getTypeAlign(T) / 8);
MakeNode(Dst, Ex, Pred,
- GetState(Pred)->BindExpr(Ex, ValMgr.makeIntVal(amt, Ex->getType())));
+ GetState(Pred)->BindExpr(Ex,
+ ValMgr.makeIntVal(amt.getQuantity(), Ex->getType())));
}
@@ -2695,8 +2743,13 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
void GRExprEngine::VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet & Dst) {
// Get the this object region from StoreManager.
- Loc V = getStoreManager().getThisObject(TE->getType()->getPointeeType());
- MakeNode(Dst, TE, Pred, GetState(Pred)->BindExpr(TE, V));
+ const MemRegion *R =
+ ValMgr.getRegionManager().getCXXThisRegion(TE->getType(),
+ Pred->getLocationContext());
+
+ const GRState *state = GetState(Pred);
+ SVal V = state->getSVal(loc::MemRegionVal(R));
+ MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
}
void GRExprEngine::VisitAsmStmt(AsmStmt* A, ExplodedNode* Pred,
@@ -2964,6 +3017,26 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
CheckerVisit(B, Dst, Tmp3, false);
}
+void GRExprEngine::CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ ExplodedNodeSet Tmp;
+ Visit(Ex, Pred, Tmp);
+ for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
+ const GRState *state = GetState(*I);
+
+ // Bind the temporary object to the value of the expression. Then bind
+ // the expression to the location of the object.
+ SVal V = state->getSVal(Ex);
+
+ const MemRegion *R =
+ ValMgr.getRegionManager().getCXXObjectRegion(Ex,
+ Pred->getLocationContext());
+
+ state = state->bindLoc(loc::MemRegionVal(R), V);
+ MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, loc::MemRegionVal(R)));
+ }
+}
+
//===----------------------------------------------------------------------===//
// Checker registration/lookup.
//===----------------------------------------------------------------------===//
diff --git a/lib/Analysis/GRState.cpp b/lib/Analysis/GRState.cpp
index 7415fa5f67e44..051d465f41b74 100644
--- a/lib/Analysis/GRState.cpp
+++ b/lib/Analysis/GRState.cpp
@@ -267,6 +267,9 @@ bool ScanReachableSymbols::scan(SVal val) {
if (loc::MemRegionVal *X = dyn_cast(&val))
return scan(X->getRegion());
+ if (nonloc::LocAsInteger *X = dyn_cast(&val))
+ return scan(X->getLoc());
+
if (SymbolRef Sym = val.getAsSymbol())
return visitor.VisitSymbol(Sym);
diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp
index 74fe3bf5ee5c1..87d60d340934e 100644
--- a/lib/Analysis/MemRegion.cpp
+++ b/lib/Analysis/MemRegion.cpp
@@ -17,6 +17,7 @@
#include "clang/Analysis/PathSensitive/MemRegion.h"
#include "clang/Analysis/PathSensitive/ValueManager.h"
#include "clang/Analysis/PathSensitive/AnalysisContext.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/StmtVisitor.h"
using namespace clang;
@@ -215,6 +216,18 @@ void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
ID.AddPointer(superRegion);
}
+void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const PointerType *PT,
+ const MemRegion *sRegion) {
+ ID.AddInteger((unsigned) CXXThisRegionKind);
+ ID.AddPointer(PT);
+ ID.AddPointer(sRegion);
+}
+
+void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+ CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion);
+}
+
void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
const MemRegion* superRegion, Kind k) {
ID.AddInteger((unsigned) k);
@@ -292,14 +305,14 @@ void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const {
}
void CXXObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
- QualType T,
+ Expr const *Ex,
const MemRegion *sReg) {
- ID.AddPointer(T.getTypePtr());
+ ID.AddPointer(Ex);
ID.AddPointer(sReg);
}
void CXXObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
- ProfileRegion(ID, T, getSuperRegion());
+ ProfileRegion(ID, Ex, getSuperRegion());
}
//===----------------------------------------------------------------------===//
@@ -343,6 +356,10 @@ void CompoundLiteralRegion::dumpToStream(llvm::raw_ostream& os) const {
os << "{ " << (void*) CL << " }";
}
+void CXXThisRegion::dumpToStream(llvm::raw_ostream &os) const {
+ os << "this";
+}
+
void ElementRegion::dumpToStream(llvm::raw_ostream& os) const {
os << "element{" << superRegion << ','
<< Index << ',' << getElementType().getAsString() << '}';
@@ -551,7 +568,7 @@ const SymbolicRegion *MemRegionManager::getSymbolicRegion(SymbolRef sym) {
return getSubRegion(sym, getUnknownRegion());
}
-const FieldRegion *
+const FieldRegion*
MemRegionManager::getFieldRegion(const FieldDecl* d,
const MemRegion* superRegion){
return getSubRegion(d, superRegion);
@@ -563,9 +580,22 @@ MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
return getSubRegion(d, superRegion);
}
-const CXXObjectRegion *
-MemRegionManager::getCXXObjectRegion(QualType T) {
- return getSubRegion(T, getUnknownRegion());
+const CXXObjectRegion*
+MemRegionManager::getCXXObjectRegion(Expr const *E,
+ LocationContext const *LC) {
+ const StackFrameContext *SFC = LC->getCurrentStackFrame();
+ assert(SFC);
+ return getSubRegion(E, getStackLocalsRegion(SFC));
+}
+
+const CXXThisRegion*
+MemRegionManager::getCXXThisRegion(QualType thisPointerTy,
+ const LocationContext *LC) {
+ const StackFrameContext *STC = LC->getCurrentStackFrame();
+ assert(STC);
+ const PointerType *PT = thisPointerTy->getAs();
+ assert(PT);
+ return getSubRegion(PT, getStackArgumentsRegion(STC));
}
const AllocaRegion*
@@ -592,20 +622,11 @@ bool MemRegion::hasStackStorage() const {
return isa(getMemorySpace());
}
-bool MemRegion::hasHeapStorage() const {
- return isa(getMemorySpace());
-}
-
-bool MemRegion::hasHeapOrStackStorage() const {
- const MemSpaceRegion *MS = getMemorySpace();
- return isa(MS) || isa(MS);
-}
-
-bool MemRegion::hasGlobalsStorage() const {
- return isa(getMemorySpace());
+bool MemRegion::hasStackNonParametersStorage() const {
+ return isa(getMemorySpace());
}
-bool MemRegion::hasParametersStorage() const {
+bool MemRegion::hasStackParametersStorage() const {
return isa(getMemorySpace());
}
@@ -669,7 +690,7 @@ static bool IsCompleteType(ASTContext &Ctx, QualType Ty) {
}
RegionRawOffset ElementRegion::getAsRawOffset() const {
- int64_t offset = 0;
+ CharUnits offset = CharUnits::Zero();
const ElementRegion *ER = this;
const MemRegion *superR = NULL;
ASTContext &C = getContext();
@@ -694,7 +715,7 @@ RegionRawOffset ElementRegion::getAsRawOffset() const {
break;
}
- int64_t size = (int64_t) (C.getTypeSize(elemType) / 8);
+ CharUnits size = C.getTypeSizeInChars(elemType);
offset += (i * size);
}
@@ -707,7 +728,7 @@ RegionRawOffset ElementRegion::getAsRawOffset() const {
}
assert(superR && "super region cannot be NULL");
- return RegionRawOffset(superR, offset);
+ return RegionRawOffset(superR, offset.getQuantity());
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Analysis/OSAtomicChecker.cpp b/lib/Analysis/OSAtomicChecker.cpp
index cf16796b1b146..9d34e9ec5c8bd 100644
--- a/lib/Analysis/OSAtomicChecker.cpp
+++ b/lib/Analysis/OSAtomicChecker.cpp
@@ -103,19 +103,9 @@ bool OSAtomicChecker::EvalOSAtomicCompareAndSwap(CheckerContext &C,
SVal location = state->getSVal(theValueExpr);
// Here we should use the value type of the region as the load type.
QualType LoadTy;
- if (const MemRegion *R = location.getAsRegion()) {
- // We must be careful, as SymbolicRegions aren't typed.
- const MemRegion *strippedR = R->StripCasts();
- // FIXME: This isn't quite the right solution. One test case in 'test/Analysis/NSString.m'
- // is giving the wrong result.
- const TypedRegion *typedR =
- isa(strippedR) ? cast(R) :
- dyn_cast(strippedR);
-
- if (typedR) {
- LoadTy = typedR->getValueType(Ctx);
- location = loc::MemRegionVal(typedR);
- }
+ if (const TypedRegion *TR =
+ dyn_cast_or_null(location.getAsRegion())) {
+ LoadTy = TR->getValueType(Ctx);
}
Engine.EvalLoad(Tmp, const_cast(theValueExpr), C.getPredecessor(),
state, location, OSAtomicLoadTag, LoadTy);
@@ -184,14 +174,22 @@ bool OSAtomicChecker::EvalOSAtomicCompareAndSwap(CheckerContext &C,
E2 = TmpStore.end(); I2 != E2; ++I2) {
ExplodedNode *predNew = *I2;
const GRState *stateNew = predNew->getState();
- SVal Res = Engine.getValueManager().makeTruthVal(true, CE->getType());
+ // Check for 'void' return type if we have a bogus function prototype.
+ SVal Res = UnknownVal();
+ QualType T = CE->getType();
+ if (!T->isVoidType())
+ Res = Engine.getValueManager().makeTruthVal(true, T);
C.GenerateNode(stateNew->BindExpr(CE, Res), predNew);
}
}
// Were they not equal?
if (const GRState *stateNotEqual = stateLoad->Assume(Cmp, false)) {
- SVal Res = Engine.getValueManager().makeTruthVal(false, CE->getType());
+ // Check for 'void' return type if we have a bogus function prototype.
+ SVal Res = UnknownVal();
+ QualType T = CE->getType();
+ if (!T->isVoidType())
+ Res = Engine.getValueManager().makeTruthVal(false, CE->getType());
C.GenerateNode(stateNotEqual->BindExpr(CE, Res), N);
}
}
diff --git a/lib/Analysis/RangeConstraintManager.cpp b/lib/Analysis/RangeConstraintManager.cpp
index 7330b6261479b..2cf3dfb6d0dbd 100644
--- a/lib/Analysis/RangeConstraintManager.cpp
+++ b/lib/Analysis/RangeConstraintManager.cpp
@@ -234,7 +234,8 @@ namespace {
class RangeConstraintManager : public SimpleConstraintManager{
RangeSet GetRange(const GRState *state, SymbolRef sym);
public:
- RangeConstraintManager() {}
+ RangeConstraintManager(GRSubEngine &subengine)
+ : SimpleConstraintManager(subengine) {}
const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V);
@@ -273,8 +274,9 @@ private:
} // end anonymous namespace
-ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager&) {
- return new RangeConstraintManager();
+ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager&,
+ GRSubEngine &subeng) {
+ return new RangeConstraintManager(subeng);
}
const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState* St,
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index 3bc9dccda6bfb..9b5b44be64273 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -28,9 +28,12 @@
using namespace clang;
-#define HEAP_UNDEFINED 0
#define USE_EXPLICIT_COMPOUND 0
+//===----------------------------------------------------------------------===//
+// Representation of value bindings.
+//===----------------------------------------------------------------------===//
+
namespace {
class BindingVal {
public:
@@ -77,8 +80,41 @@ llvm::raw_ostream& operator<<(llvm::raw_ostream& os, BindingVal V) {
}
} // end llvm namespace
+//===----------------------------------------------------------------------===//
+// Representation of binding keys.
+//===----------------------------------------------------------------------===//
+
+namespace {
+ class BindingKey : public std::pair {
+public:
+ explicit BindingKey(const MemRegion *r, uint64_t offset)
+ : std::pair(r, offset) { assert(r); }
+
+ const MemRegion *getRegion() const { return first; }
+ uint64_t getOffset() const { return second; }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ ID.AddPointer(getRegion());
+ ID.AddInteger(getOffset());
+ }
+
+ static BindingKey Make(const MemRegion *R);
+};
+} // end anonymous namespace
+
+namespace llvm {
+ static inline
+ llvm::raw_ostream& operator<<(llvm::raw_ostream& os, BindingKey K) {
+ os << '(' << K.getRegion() << ',' << K.getOffset() << ')';
+ return os;
+ }
+} // end llvm namespace
+
+//===----------------------------------------------------------------------===//
// Actual Store type.
-typedef llvm::ImmutableMap RegionBindings;
+//===----------------------------------------------------------------------===//
+
+typedef llvm::ImmutableMap RegionBindings;
//===----------------------------------------------------------------------===//
// Fine-grained control of RegionStoreManager.
@@ -283,6 +319,16 @@ private:
void RemoveSubRegionBindings(RegionBindings &B, const MemRegion *R,
RegionStoreSubRegionMap &M);
+ RegionBindings Add(RegionBindings B, BindingKey K, BindingVal V);
+ RegionBindings Add(RegionBindings B, const MemRegion *R, BindingVal V);
+
+ const BindingVal *Lookup(RegionBindings B, BindingKey K);
+ const BindingVal *Lookup(RegionBindings B, const MemRegion *R);
+
+ RegionBindings Remove(RegionBindings B, BindingKey K);
+ RegionBindings Remove(RegionBindings B, const MemRegion *R);
+ Store Remove(Store store, BindingKey K);
+
public:
const GRState *Bind(const GRState *state, Loc LV, SVal V);
@@ -308,6 +354,7 @@ public:
Store KillStruct(Store store, const TypedRegion* R);
Store Remove(Store store, Loc LV);
+
//===------------------------------------------------------------------===//
// Loading values from regions.
@@ -438,7 +485,7 @@ RegionStoreManager::getRegionStoreSubRegionMap(Store store) {
llvm::SmallVector WL;
for (RegionBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I)
- if (const SubRegion *R = dyn_cast(I.getKey()))
+ if (const SubRegion *R = dyn_cast(I.getKey().getRegion()))
M->process(WL, R);
// We also need to record in the subregion map "intermediate" regions that
@@ -467,8 +514,8 @@ void RegionStoreManager::RemoveSubRegionBindings(RegionBindings &B,
for (llvm::tie(I, E) = M.begin_end(R); I != E; ++I)
RemoveSubRegionBindings(B, *I, M);
-
- B = RBFactory.Remove(B, R);
+
+ B = Remove(B, R);
}
const GRState *RegionStoreManager::InvalidateRegions(const GRState *state,
@@ -544,8 +591,8 @@ const GRState *RegionStoreManager::InvalidateRegions(const GRState *state,
// Invalidate the region by setting its default value to
// conjured symbol. The type of the symbol is irrelavant.
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, Ctx.IntTy,
- Count);
- B = RBFactory.Add(B, R, BindingVal(V, BindingVal::Default));
+ Count);
+ B = Add(B, R, BindingVal(V, BindingVal::Default));
continue;
}
@@ -566,7 +613,7 @@ const GRState *RegionStoreManager::InvalidateRegions(const GRState *state,
// conjured symbol. The type of the symbol is irrelavant.
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, Ctx.IntTy,
Count);
- B = RBFactory.Add(B, R, BindingVal(V, BindingVal::Default));
+ B = Add(B, R, BindingVal(V, BindingVal::Default));
continue;
}
@@ -574,7 +621,7 @@ const GRState *RegionStoreManager::InvalidateRegions(const GRState *state,
// Set the default value of the array to conjured symbol.
DefinedOrUnknownSVal V =
ValMgr.getConjuredSymbolVal(R, Ex, AT->getElementType(), Count);
- B = RBFactory.Add(B, R, BindingVal(V, BindingVal::Default));
+ B = Add(B, R, BindingVal(V, BindingVal::Default));
continue;
}
@@ -583,14 +630,14 @@ const GRState *RegionStoreManager::InvalidateRegions(const GRState *state,
// For fields and elements whose super region has also been invalidated,
// only remove the old binding. The super region will get set with a
// default value from which we can lazily derive a new symbolic value.
- B = RBFactory.Remove(B, R);
+ B = Remove(B, R);
continue;
}
// Invalidate the binding.
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, T, Count);
assert(SymbolManager::canSymbolicate(T) || V.isUnknown());
- B = RBFactory.Add(B, R, BindingVal(V, BindingVal::Direct));
+ B = Add(B, R, BindingVal(V, BindingVal::Direct));
}
// Create a new state with the updated bindings.
@@ -723,6 +770,8 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
const MemRegion *R) {
switch (R->getKind()) {
+ case MemRegion::CXXThisRegionKind:
+ assert(0 && "Cannot get size of 'this' region");
case MemRegion::GenericMemSpaceRegionKind:
case MemRegion::StackLocalsSpaceRegionKind:
case MemRegion::StackArgumentsSpaceRegionKind:
@@ -877,6 +926,9 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
// Technically this can happen if people do funny things with casts.
return UnknownVal();
+ case MemRegion::CXXThisRegionKind:
+ assert(0 &&
+ "Cannot perform pointer arithmetic on implicit argument 'this'");
case MemRegion::GenericMemSpaceRegionKind:
case MemRegion::StackLocalsSpaceRegionKind:
case MemRegion::StackArgumentsSpaceRegionKind:
@@ -921,7 +973,7 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
Optional RegionStoreManager::getDirectBinding(RegionBindings B,
const MemRegion *R) {
- if (const BindingVal *BV = B.lookup(R))
+ if (const BindingVal *BV = Lookup(B, R))
return Optional::create(BV->getDirectValue());
return Optional();
@@ -935,7 +987,7 @@ Optional RegionStoreManager::getDefaultBinding(RegionBindings B,
if (TR->getValueType(getContext())->isUnionType())
return UnknownVal();
- if (BindingVal const *V = B.lookup(R))
+ if (const BindingVal *V = Lookup(B, R))
return Optional::create(V->getDefaultValue());
return Optional();
@@ -943,7 +995,7 @@ Optional RegionStoreManager::getDefaultBinding(RegionBindings B,
Optional RegionStoreManager::getBinding(RegionBindings B,
const MemRegion *R) {
- if (const BindingVal *BV = B.lookup(R))
+ if (const BindingVal *BV = Lookup(B, R))
return Optional::create(BV->getValue());
return Optional();
@@ -1051,22 +1103,46 @@ RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
if (const FieldRegion* FR = dyn_cast(R))
return SValuator::CastResult(state,
- CastRetrievedVal(RetrieveField(state, FR), FR, T));
-
- if (const ElementRegion* ER = dyn_cast(R))
+ CastRetrievedVal(RetrieveField(state, FR), FR,
+ T, false));
+
+ if (const ElementRegion* ER = dyn_cast(R)) {
+ // FIXME: Here we actually perform an implicit conversion from the loaded
+ // value to the element type. Eventually we want to compose these values
+ // more intelligently. For example, an 'element' can encompass multiple
+ // bound regions (e.g., several bound bytes), or could be a subset of
+ // a larger value.
return SValuator::CastResult(state,
- CastRetrievedVal(RetrieveElement(state, ER), ER, T));
-
- if (const ObjCIvarRegion *IVR = dyn_cast(R))
+ CastRetrievedVal(RetrieveElement(state, ER),
+ ER, T, false));
+ }
+
+ if (const ObjCIvarRegion *IVR = dyn_cast(R)) {
+ // FIXME: Here we actually perform an implicit conversion from the loaded
+ // value to the ivar type. What we should model is stores to ivars
+ // that blow past the extent of the ivar. If the address of the ivar is
+ // reinterpretted, it is possible we stored a different value that could
+ // fit within the ivar. Either we need to cast these when storing them
+ // or reinterpret them lazily (as we do here).
return SValuator::CastResult(state,
- CastRetrievedVal(RetrieveObjCIvar(state, IVR), IVR, T));
+ CastRetrievedVal(RetrieveObjCIvar(state, IVR),
+ IVR, T, false));
+ }
- if (const VarRegion *VR = dyn_cast(R))
+ if (const VarRegion *VR = dyn_cast(R)) {
+ // FIXME: Here we actually perform an implicit conversion from the loaded
+ // value to the variable type. What we should model is stores to variables
+ // that blow past the extent of the variable. If the address of the
+ // variable is reinterpretted, it is possible we stored a different value
+ // that could fit within the variable. Either we need to cast these when
+ // storing them or reinterpret them lazily (as we do here).
return SValuator::CastResult(state,
- CastRetrievedVal(RetrieveVar(state, VR), VR, T));
+ CastRetrievedVal(RetrieveVar(state, VR), VR, T,
+ false));
+ }
RegionBindings B = GetRegionBindings(state->getStore());
- RegionBindings::data_type* V = B.lookup(R);
+ const BindingVal *V = Lookup(B, R);
// Check if the region has a binding.
if (V)
@@ -1076,12 +1152,7 @@ RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
// The location does not have a bound value. This means that it has
// the value it had upon its creation and/or entry to the analyzed
// function/method. These are either symbolic values or 'undefined'.
-
-#if HEAP_UNDEFINED
- if (R->hasHeapOrStackStorage()) {
-#else
- if (R->hasStackStorage()) {
-#endif
+ if (R->hasStackNonParametersStorage()) {
// All stack variables are considered to have undefined values
// upon creation. All heap allocated blocks are considered to
// have undefined values as well unless they are explicitly bound
@@ -1124,7 +1195,7 @@ SVal RegionStoreManager::RetrieveElement(const GRState* state,
const ElementRegion* R) {
// Check if the region has a binding.
RegionBindings B = GetRegionBindings(state->getStore());
- if (Optional V = getDirectBinding(B, R))
+ if (Optional V = getDirectBinding(B, R))
return *V;
const MemRegion* superR = R->getSuperRegion();
@@ -1174,7 +1245,7 @@ SVal RegionStoreManager::RetrieveElement(const GRState* state,
// Other cases: give up.
return UnknownVal();
}
-
+
return RetrieveFieldOrElementCommon(state, R, R->getElementType(), superR);
}
@@ -1240,8 +1311,7 @@ SVal RegionStoreManager::RetrieveFieldOrElementCommon(const GRState *state,
cast(lazyBindingRegion));
}
- if (R->hasStackStorage() && !R->hasParametersStorage()) {
-
+ if (R->hasStackNonParametersStorage()) {
if (isa(R)) {
// Currently we don't reason specially about Clang-style vectors. Check
// if superR is a vector and if so return Unknown.
@@ -1369,15 +1439,9 @@ SVal RegionStoreManager::RetrieveArray(const GRState *state,
//===----------------------------------------------------------------------===//
Store RegionStoreManager::Remove(Store store, Loc L) {
- const MemRegion* R = 0;
-
if (isa(L))
- R = cast(L).getRegion();
-
- if (R) {
- RegionBindings B = GetRegionBindings(store);
- return RBFactory.Remove(B, R).getRoot();
- }
+ if (const MemRegion* R = cast(L).getRegion())
+ return Remove(store, BindingKey::Make(R));
return store;
}
@@ -1436,8 +1500,8 @@ const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) {
// Perform the binding.
RegionBindings B = GetRegionBindings(state->getStore());
- return state->makeWithStore(
- RBFactory.Add(B, R, BindingVal(V, BindingVal::Direct)).getRoot());
+ return state->makeWithStore(Add(B, R,
+ BindingVal(V, BindingVal::Direct)).getRoot());
}
const GRState *RegionStoreManager::BindDecl(const GRState *ST,
@@ -1483,9 +1547,9 @@ const GRState *RegionStoreManager::setImplicitDefaultValue(const GRState *state,
else {
return state;
}
-
- B = RBFactory.Add(B, R, BindingVal(V, BindingVal::Default));
- return state->makeWithStore(B.getRoot());
+
+ return state->makeWithStore(Add(B, R,
+ BindingVal(V, BindingVal::Default)).getRoot());
}
const GRState *RegionStoreManager::BindArray(const GRState *state,
@@ -1610,8 +1674,7 @@ RegionStoreManager::BindStruct(const GRState *state, const TypedRegion* R,
if (FI != FE) {
Store store = state->getStore();
RegionBindings B = GetRegionBindings(store);
- B = RBFactory.Add(B, R,
- BindingVal(ValMgr.makeIntVal(0, false), BindingVal::Default));
+ B = Add(B, R, BindingVal(ValMgr.makeIntVal(0, false), BindingVal::Default));
state = state->makeWithStore(B.getRoot());
}
@@ -1625,7 +1688,7 @@ Store RegionStoreManager::KillStruct(Store store, const TypedRegion* R) {
RemoveSubRegionBindings(B, R, *SubRegions);
// Set the default value of the struct region to "unknown".
- B = RBFactory.Add(B, R, BindingVal(UnknownVal(), BindingVal::Default));
+ B = Add(B, R, BindingVal(UnknownVal(), BindingVal::Default));
return B.getRoot();
}
@@ -1646,8 +1709,58 @@ RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
// Now copy the bindings. This amounts to just binding 'V' to 'R'. This
// results in a zero-copy algorithm.
- return state->makeWithStore(
- RBFactory.Add(B, R, BindingVal(V, BindingVal::Direct)).getRoot());
+ return state->makeWithStore(Add(B, R,
+ BindingVal(V, BindingVal::Direct)).getRoot());
+}
+
+//===----------------------------------------------------------------------===//
+// "Raw" retrievals and bindings.
+//===----------------------------------------------------------------------===//
+
+BindingKey BindingKey::Make(const MemRegion *R) {
+ if (const ElementRegion *ER = dyn_cast(R)) {
+ const RegionRawOffset &O = ER->getAsRawOffset();
+
+ if (O.getRegion())
+ return BindingKey(O.getRegion(), O.getByteOffset());
+
+ // FIXME: There are some ElementRegions for which we cannot compute
+ // raw offsets yet, including regions with symbolic offsets.
+ }
+
+ return BindingKey(R, 0);
+}
+
+RegionBindings RegionStoreManager::Add(RegionBindings B, BindingKey K,
+ BindingVal V) {
+ return RBFactory.Add(B, K, V);
+}
+
+RegionBindings RegionStoreManager::Add(RegionBindings B, const MemRegion *R,
+ BindingVal V) {
+ return Add(B, BindingKey::Make(R), V);
+}
+
+const BindingVal *RegionStoreManager::Lookup(RegionBindings B, BindingKey K) {
+ return B.lookup(K);
+}
+
+const BindingVal *RegionStoreManager::Lookup(RegionBindings B,
+ const MemRegion *R) {
+ return Lookup(B, BindingKey::Make(R));
+}
+
+RegionBindings RegionStoreManager::Remove(RegionBindings B, BindingKey K) {
+ return RBFactory.Remove(B, K);
+}
+
+RegionBindings RegionStoreManager::Remove(RegionBindings B, const MemRegion *R){
+ return Remove(B, BindingKey::Make(R));
+}
+
+Store RegionStoreManager::Remove(Store store, BindingKey K) {
+ RegionBindings B = GetRegionBindings(store);
+ return Remove(B, K).getRoot();
}
//===----------------------------------------------------------------------===//
@@ -1674,7 +1787,7 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
// Scan the direct bindings for "intermediate" roots.
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- const MemRegion *R = I.getKey();
+ const MemRegion *R = I.getKey().getRegion();
IntermediateRoots.push_back(R);
}
@@ -1831,13 +1944,13 @@ tryAgain:
// as live. We now remove all the regions that are dead from the store
// as well as update DSymbols with the set symbols that are now dead.
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- const MemRegion* R = I.getKey();
+ const MemRegion* R = I.getKey().getRegion();
// If this region live? Is so, none of its symbols are dead.
if (Visited.count(std::make_pair(&state, R)))
continue;
// Remove this dead region from the store.
- store = Remove(store, ValMgr.makeLoc(R));
+ store = Remove(store, I.getKey());
// Mark all non-live symbols that this region references as dead.
if (const SymbolicRegion* SymR = dyn_cast(R))
diff --git a/lib/Analysis/ReturnStackAddressChecker.cpp b/lib/Analysis/ReturnStackAddressChecker.cpp
index 3a6d8a41c0691..4d7e8ade98f77 100644
--- a/lib/Analysis/ReturnStackAddressChecker.cpp
+++ b/lib/Analysis/ReturnStackAddressChecker.cpp
@@ -67,6 +67,9 @@ void ReturnStackAddressChecker::PreVisitReturnStmt(CheckerContext &C,
llvm::raw_svector_ostream os(buf);
SourceRange range;
+ // Get the base region, stripping away fields and elements.
+ R = R->getBaseRegion();
+
// Check if the region is a compound literal.
if (const CompoundLiteralRegion* CR = dyn_cast(R)) {
const CompoundLiteralExpr* CL = CR->getLiteralExpr();
@@ -92,13 +95,18 @@ void ReturnStackAddressChecker::PreVisitReturnStmt(CheckerContext &C,
<< C.getSourceManager().getInstantiationLineNumber(L)
<< " returned to caller";
}
- else {
+ else if (const VarRegion *VR = dyn_cast(R)) {
os << "Address of stack memory associated with local variable '"
- << R->getString() << "' returned.";
+ << VR->getString() << "' returned";
+ range = VR->getDecl()->getSourceRange();
+ }
+ else {
+ assert(false && "Invalid region in ReturnStackAddressChecker.");
+ return;
}
RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
- report->addRange(RS->getSourceRange());
+ report->addRange(RetE->getSourceRange());
if (range.isValid())
report->addRange(range);
diff --git a/lib/Analysis/SVals.cpp b/lib/Analysis/SVals.cpp
index 9163b2725273a..fbdb73b0ef2e8 100644
--- a/lib/Analysis/SVals.cpp
+++ b/lib/Analysis/SVals.cpp
@@ -97,6 +97,10 @@ const MemRegion *SVal::getAsRegion() const {
if (const loc::MemRegionVal *X = dyn_cast(this))
return X->getRegion();
+ if (const nonloc::LocAsInteger *X = dyn_cast(this)) {
+ return X->getLoc().getAsRegion();
+ }
+
return 0;
}
diff --git a/lib/Analysis/SValuator.cpp b/lib/Analysis/SValuator.cpp
index 49bc0c4c59885..8392fcf65a2ca 100644
--- a/lib/Analysis/SValuator.cpp
+++ b/lib/Analysis/SValuator.cpp
@@ -62,8 +62,12 @@ SValuator::CastResult SValuator::EvalCast(SVal val, const GRState *state,
ASTContext &C = ValMgr.getContext();
// For const casts, just propagate the value.
- if (C.hasSameUnqualifiedType(castTy, originalTy))
- return CastResult(state, val);
+ if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType())
+ if (C.hasSameUnqualifiedType(castTy, originalTy))
+ return CastResult(state, val);
+
+ if (castTy->isIntegerType() && originalTy->isIntegerType())
+ return CastResult(state, EvalCastNL(cast(val), castTy));
// Check for casts from pointers to integers.
if (castTy->isIntegerType() && Loc::IsLocType(originalTy))
diff --git a/lib/Analysis/SimpleConstraintManager.cpp b/lib/Analysis/SimpleConstraintManager.cpp
index 23c3b41758359..eca20d574db3f 100644
--- a/lib/Analysis/SimpleConstraintManager.cpp
+++ b/lib/Analysis/SimpleConstraintManager.cpp
@@ -65,25 +65,10 @@ const GRState *SimpleConstraintManager::Assume(const GRState *state,
return Assume(state, cast(Cond), Assumption);
}
-const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc Cond,
- bool Assumption) {
-
- state = AssumeAux(state, Cond, Assumption);
-
- // EvalAssume is used to call into the GRTransferFunction object to perform
- // any checker-specific update of the state based on this assumption being
- // true or false.
-
- if (!state)
- return 0;
-
- std::vector >::iterator
- I = state->checker_begin(), E = state->checker_end();
-
- for (; I != E; ++I) {
- state = I->second->EvalAssume(state, Cond, Assumption);
- }
- return state->getTransferFuncs().EvalAssume(state, Cond, Assumption);
+const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc cond,
+ bool assumption) {
+ state = AssumeAux(state, cond, assumption);
+ return SU.ProcessAssume(state, cond, assumption);
}
const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
@@ -130,26 +115,10 @@ const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
}
const GRState *SimpleConstraintManager::Assume(const GRState *state,
- NonLoc Cond,
- bool Assumption) {
-
- state = AssumeAux(state, Cond, Assumption);
-
- // EvalAssume is used to call into the GRTransferFunction object to perform
- // any checker-specific update of the state based on this assumption being
- // true or false.
-
- if (!state)
- return 0;
-
- std::vector >::iterator
- I = state->checker_begin(), E = state->checker_end();
-
- for (; I != E; ++I) {
- state = I->second->EvalAssume(state, Cond, Assumption);
- }
-
- return state->getTransferFuncs().EvalAssume(state, Cond, Assumption);
+ NonLoc cond,
+ bool assumption) {
+ state = AssumeAux(state, cond, assumption);
+ return SU.ProcessAssume(state, cond, assumption);
}
const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
diff --git a/lib/Analysis/SimpleConstraintManager.h b/lib/Analysis/SimpleConstraintManager.h
index 0c58440ac0b6d..818239831948a 100644
--- a/lib/Analysis/SimpleConstraintManager.h
+++ b/lib/Analysis/SimpleConstraintManager.h
@@ -20,8 +20,9 @@
namespace clang {
class SimpleConstraintManager : public ConstraintManager {
+ GRSubEngine &SU;
public:
- SimpleConstraintManager() {}
+ SimpleConstraintManager(GRSubEngine &subengine) : SU(subengine) {}
virtual ~SimpleConstraintManager();
//===------------------------------------------------------------------===//
diff --git a/lib/Analysis/SimpleSValuator.cpp b/lib/Analysis/SimpleSValuator.cpp
index 2afcd3e847cdd..8f2f5a1b134c2 100644
--- a/lib/Analysis/SimpleSValuator.cpp
+++ b/lib/Analysis/SimpleSValuator.cpp
@@ -53,13 +53,13 @@ SVal SimpleSValuator::EvalCastNL(NonLoc val, QualType castTy) {
if (isLocType)
return LI->getLoc();
+ // FIXME: Correctly support promotions/truncations.
ASTContext &Ctx = ValMgr.getContext();
-
- // FIXME: Support promotions/truncations.
- if (Ctx.getTypeSize(castTy) == Ctx.getTypeSize(Ctx.VoidPtrTy))
+ unsigned castSize = Ctx.getTypeSize(castTy);
+ if (castSize == LI->getNumBits())
return val;
- return UnknownVal();
+ return ValMgr.makeLocAsInteger(LI->getLoc(), castSize);
}
if (const SymExpr *se = val.getAsSymbolicExpression()) {
diff --git a/lib/Analysis/Store.cpp b/lib/Analysis/Store.cpp
index 8d911b844fc04..1724a9250c251 100644
--- a/lib/Analysis/Store.cpp
+++ b/lib/Analysis/Store.cpp
@@ -13,6 +13,7 @@
#include "clang/Analysis/PathSensitive/Store.h"
#include "clang/Analysis/PathSensitive/GRState.h"
+#include "clang/AST/CharUnits.h"
using namespace clang;
@@ -77,6 +78,7 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
// Process region cast according to the kind of the region being cast.
switch (R->getKind()) {
+ case MemRegion::CXXThisRegionKind:
case MemRegion::GenericMemSpaceRegionKind:
case MemRegion::StackLocalsSpaceRegionKind:
case MemRegion::StackArgumentsSpaceRegionKind:
@@ -137,9 +139,9 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
if (!baseR)
return NULL;
- int64_t off = rawOff.getByteOffset();
+ CharUnits off = CharUnits::fromQuantity(rawOff.getByteOffset());
- if (off == 0) {
+ if (off.isZero()) {
// Edge case: we are at 0 bytes off the beginning of baseR. We
// check to see if type we are casting to is the same as the base
// region. If so, just return the base region.
@@ -167,7 +169,7 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
// We can only compute sizeof(PointeeTy) if it is a complete type.
if (IsCompleteType(Ctx, PointeeTy)) {
// Compute the size in **bytes**.
- int64_t pointeeTySize = (int64_t) (Ctx.getTypeSize(PointeeTy) / 8);
+ CharUnits pointeeTySize = Ctx.getTypeSizeInChars(PointeeTy);
// Is the offset a multiple of the size? If so, we can layer the
// ElementRegion (with elementType == PointeeTy) directly on top of
@@ -181,7 +183,7 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
if (!newSuperR) {
// Create an intermediate ElementRegion to represent the raw byte.
// This will be the super region of the final ElementRegion.
- newSuperR = MakeElementRegion(baseR, Ctx.CharTy, off);
+ newSuperR = MakeElementRegion(baseR, Ctx.CharTy, off.getQuantity());
}
return MakeElementRegion(newSuperR, PointeeTy, newIndex);
@@ -196,23 +198,29 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
/// implicit casts that arise from loads from regions that are reinterpreted
/// as another region.
-SVal StoreManager::CastRetrievedVal(SVal V, const TypedRegion *R,
- QualType castTy) {
+SVal StoreManager::CastRetrievedVal(SVal V, const TypedRegion *R,
+ QualType castTy, bool performTestOnly) {
-#ifndef NDEBUG
if (castTy.isNull())
return V;
ASTContext &Ctx = ValMgr.getContext();
- QualType T = R->getValueType(Ctx);
-
- // Automatically translate references to pointers.
- if (const ReferenceType *RT = T->getAs())
- T = Ctx.getPointerType(RT->getPointeeType());
-
- assert(ValMgr.getContext().hasSameUnqualifiedType(castTy, T));
-#endif
+ if (performTestOnly) {
+ // Automatically translate references to pointers.
+ QualType T = R->getValueType(Ctx);
+ if (const ReferenceType *RT = T->getAs())
+ T = Ctx.getPointerType(RT->getPointeeType());
+
+ assert(ValMgr.getContext().hasSameUnqualifiedType(castTy, T));
+ return V;
+ }
+
+ if (const Loc *L = dyn_cast(&V))
+ return ValMgr.getSValuator().EvalCastL(*L, castTy);
+ else if (const NonLoc *NL = dyn_cast(&V))
+ return ValMgr.getSValuator().EvalCastNL(*NL, castTy);
+
return V;
}
@@ -240,8 +248,3 @@ SVal StoreManager::getLValueCompoundLiteral(const CompoundLiteralExpr* CL,
const LocationContext *LC) {
return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC));
}
-
-Loc StoreManager::getThisObject(QualType T) {
- const CXXObjectRegion *R = MRMgr.getCXXObjectRegion(T);
- return loc::MemRegionVal(R);
-}
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 4351f66be32f2..abbf6f9b6e410 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -541,19 +541,46 @@ static bool ModifierIs(const char *Modifier, unsigned ModifierLen,
return StrLen-1 == ModifierLen && !memcmp(Modifier, Str, StrLen-1);
}
+/// ScanForward - Scans forward, looking for the given character, skipping
+/// nested clauses and escaped characters.
+static const char *ScanFormat(const char *I, const char *E, char Target) {
+ unsigned Depth = 0;
+
+ for ( ; I != E; ++I) {
+ if (Depth == 0 && *I == Target) return I;
+ if (Depth != 0 && *I == '}') Depth--;
+
+ if (*I == '%') {
+ I++;
+ if (I == E) break;
+
+ // Escaped characters get implicitly skipped here.
+
+ // Format specifier.
+ if (!isdigit(*I) && !ispunct(*I)) {
+ for (I++; I != E && !isdigit(*I) && *I != '{'; I++) ;
+ if (I == E) break;
+ if (*I == '{')
+ Depth++;
+ }
+ }
+ }
+ return E;
+}
+
/// HandleSelectModifier - Handle the integer 'select' modifier. This is used
/// like this: %select{foo|bar|baz}2. This means that the integer argument
/// "%2" has a value from 0-2. If the value is 0, the diagnostic prints 'foo'.
/// If the value is 1, it prints 'bar'. If it has the value 2, it prints 'baz'.
/// This is very useful for certain classes of variant diagnostics.
-static void HandleSelectModifier(unsigned ValNo,
+static void HandleSelectModifier(const DiagnosticInfo &DInfo, unsigned ValNo,
const char *Argument, unsigned ArgumentLen,
llvm::SmallVectorImpl &OutStr) {
const char *ArgumentEnd = Argument+ArgumentLen;
// Skip over 'ValNo' |'s.
while (ValNo) {
- const char *NextVal = std::find(Argument, ArgumentEnd, '|');
+ const char *NextVal = ScanFormat(Argument, ArgumentEnd, '|');
assert(NextVal != ArgumentEnd && "Value for integer select modifier was"
" larger than the number of options in the diagnostic string!");
Argument = NextVal+1; // Skip this string.
@@ -561,9 +588,10 @@ static void HandleSelectModifier(unsigned ValNo,
}
// Get the end of the value. This is either the } or the |.
- const char *EndPtr = std::find(Argument, ArgumentEnd, '|');
- // Add the value to the output string.
- OutStr.append(Argument, EndPtr);
+ const char *EndPtr = ScanFormat(Argument, ArgumentEnd, '|');
+
+ // Recursively format the result of the select clause into the output string.
+ DInfo.FormatDiagnostic(Argument, EndPtr, OutStr);
}
/// HandleIntegerSModifier - Handle the integer 's' modifier. This adds the
@@ -575,6 +603,37 @@ static void HandleIntegerSModifier(unsigned ValNo,
OutStr.push_back('s');
}
+/// HandleOrdinalModifier - Handle the integer 'ord' modifier. This
+/// prints the ordinal form of the given integer, with 1 corresponding
+/// to the first ordinal. Currently this is hard-coded to use the
+/// English form.
+static void HandleOrdinalModifier(unsigned ValNo,
+ llvm::SmallVectorImpl &OutStr) {
+ assert(ValNo != 0 && "ValNo must be strictly positive!");
+
+ llvm::raw_svector_ostream Out(OutStr);
+
+ // We could use text forms for the first N ordinals, but the numeric
+ // forms are actually nicer in diagnostics because they stand out.
+ Out << ValNo;
+
+ // It is critically important that we do this perfectly for
+ // user-written sequences with over 100 elements.
+ switch (ValNo % 100) {
+ case 11:
+ case 12:
+ case 13:
+ Out << "th"; return;
+ default:
+ switch (ValNo % 10) {
+ case 1: Out << "st"; return;
+ case 2: Out << "nd"; return;
+ case 3: Out << "rd"; return;
+ default: Out << "th"; return;
+ }
+ }
+}
+
/// PluralNumber - Parse an unsigned integer and advance Start.
static unsigned PluralNumber(const char *&Start, const char *End) {
@@ -685,11 +744,11 @@ static void HandlePluralModifier(unsigned ValNo,
}
if (EvalPluralExpr(ValNo, Argument, ExprEnd)) {
Argument = ExprEnd + 1;
- ExprEnd = std::find(Argument, ArgumentEnd, '|');
+ ExprEnd = ScanFormat(Argument, ArgumentEnd, '|');
OutStr.append(Argument, ExprEnd);
return;
}
- Argument = std::find(Argument, ArgumentEnd - 1, '|') + 1;
+ Argument = ScanFormat(Argument, ArgumentEnd - 1, '|') + 1;
}
}
@@ -702,6 +761,13 @@ FormatDiagnostic(llvm::SmallVectorImpl &OutStr) const {
const char *DiagStr = getDiags()->getDescription(getID());
const char *DiagEnd = DiagStr+strlen(DiagStr);
+ FormatDiagnostic(DiagStr, DiagEnd, OutStr);
+}
+
+void DiagnosticInfo::
+FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
+ llvm::SmallVectorImpl &OutStr) const {
+
/// FormattedArgs - Keep track of all of the arguments formatted by
/// ConvertArgToString and pass them into subsequent calls to
/// ConvertArgToString, allowing the implementation to avoid redundancies in
@@ -715,8 +781,8 @@ FormatDiagnostic(llvm::SmallVectorImpl &OutStr) const {
OutStr.append(DiagStr, StrEnd);
DiagStr = StrEnd;
continue;
- } else if (DiagStr[1] == '%') {
- OutStr.push_back('%'); // %% -> %.
+ } else if (ispunct(DiagStr[1])) {
+ OutStr.push_back(DiagStr[1]); // %% -> %.
DiagStr += 2;
continue;
}
@@ -745,8 +811,8 @@ FormatDiagnostic(llvm::SmallVectorImpl &OutStr) const {
++DiagStr; // Skip {.
Argument = DiagStr;
- for (; DiagStr[0] != '}'; ++DiagStr)
- assert(DiagStr[0] && "Mismatched {}'s in diagnostic string!");
+ DiagStr = ScanFormat(DiagStr, DiagEnd, '}');
+ assert(DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!");
ArgumentLen = DiagStr-Argument;
++DiagStr; // Skip }.
}
@@ -781,11 +847,13 @@ FormatDiagnostic(llvm::SmallVectorImpl &OutStr) const {
int Val = getArgSInt(ArgNo);
if (ModifierIs(Modifier, ModifierLen, "select")) {
- HandleSelectModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
+ HandleSelectModifier(*this, (unsigned)Val, Argument, ArgumentLen, OutStr);
} else if (ModifierIs(Modifier, ModifierLen, "s")) {
HandleIntegerSModifier(Val, OutStr);
} else if (ModifierIs(Modifier, ModifierLen, "plural")) {
HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
+ } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
+ HandleOrdinalModifier((unsigned)Val, OutStr);
} else {
assert(ModifierLen == 0 && "Unknown integer modifier");
llvm::raw_svector_ostream(OutStr) << Val;
@@ -796,11 +864,13 @@ FormatDiagnostic(llvm::SmallVectorImpl &OutStr) const {
unsigned Val = getArgUInt(ArgNo);
if (ModifierIs(Modifier, ModifierLen, "select")) {
- HandleSelectModifier(Val, Argument, ArgumentLen, OutStr);
+ HandleSelectModifier(*this, Val, Argument, ArgumentLen, OutStr);
} else if (ModifierIs(Modifier, ModifierLen, "s")) {
HandleIntegerSModifier(Val, OutStr);
} else if (ModifierIs(Modifier, ModifierLen, "plural")) {
HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
+ } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
+ HandleOrdinalModifier(Val, OutStr);
} else {
assert(ModifierLen == 0 && "Unknown integer modifier");
llvm::raw_svector_ostream(OutStr) << Val;
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index b6b5c6c1ef9ba..bba2c3ffc41fd 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -18,51 +18,38 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/Utils.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCSectionMachO.h"
+#include
using namespace clang;
//===----------------------------------------------------------------------===//
// Common code shared among targets.
//===----------------------------------------------------------------------===//
-static void Define(std::vector &Buf, const llvm::StringRef &Macro,
- const llvm::StringRef &Val = "1") {
- const char *Def = "#define ";
- Buf.insert(Buf.end(), Def, Def+strlen(Def));
- Buf.insert(Buf.end(), Macro.begin(), Macro.end());
- Buf.push_back(' ');
- Buf.insert(Buf.end(), Val.begin(), Val.end());
- Buf.push_back('\n');
-}
-
/// DefineStd - Define a macro name and standard variants. For example if
/// MacroName is "unix", then this will define "__unix", "__unix__", and "unix"
/// when in GNU mode.
-static void DefineStd(std::vector &Buf, const char *MacroName,
+static void DefineStd(MacroBuilder &Builder, llvm::StringRef MacroName,
const LangOptions &Opts) {
assert(MacroName[0] != '_' && "Identifier should be in the user's namespace");
// If in GNU mode (e.g. -std=gnu99 but not -std=c99) define the raw identifier
// in the user's namespace.
if (Opts.GNUMode)
- Define(Buf, MacroName);
+ Builder.defineMacro(MacroName);
// Define __unix.
- llvm::SmallString<20> TmpStr;
- TmpStr = "__";
- TmpStr += MacroName;
- Define(Buf, TmpStr.str());
+ Builder.defineMacro("__" + MacroName);
// Define __unix__.
- TmpStr += "__";
- Define(Buf, TmpStr.str());
+ Builder.defineMacro("__" + MacroName + "__");
}
//===----------------------------------------------------------------------===//
@@ -74,44 +61,44 @@ template
class OSTargetInfo : public TgtInfo {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- std::vector &Defines) const=0;
+ MacroBuilder &Builder) const=0;
public:
OSTargetInfo(const std::string& triple) : TgtInfo(triple) {}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- TgtInfo::getTargetDefines(Opts, Defines);
- getOSDefines(Opts, TgtInfo::getTriple(), Defines);
+ MacroBuilder &Builder) const {
+ TgtInfo::getTargetDefines(Opts, Builder);
+ getOSDefines(Opts, TgtInfo::getTriple(), Builder);
}
};
} // end anonymous namespace
-static void getDarwinDefines(std::vector &Defs, const LangOptions &Opts) {
- Define(Defs, "__APPLE_CC__", "5621");
- Define(Defs, "__APPLE__");
- Define(Defs, "__MACH__");
- Define(Defs, "OBJC_NEW_PROPERTIES");
+static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts) {
+ Builder.defineMacro("__APPLE_CC__", "5621");
+ Builder.defineMacro("__APPLE__");
+ Builder.defineMacro("__MACH__");
+ Builder.defineMacro("OBJC_NEW_PROPERTIES");
// __weak is always defined, for use in blocks and with objc pointers.
- Define(Defs, "__weak", "__attribute__((objc_gc(weak)))");
+ Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
// Darwin defines __strong even in C mode (just to nothing).
if (!Opts.ObjC1 || Opts.getGCMode() == LangOptions::NonGC)
- Define(Defs, "__strong", "");
+ Builder.defineMacro("__strong", "");
else
- Define(Defs, "__strong", "__attribute__((objc_gc(strong)))");
+ Builder.defineMacro("__strong", "__attribute__((objc_gc(strong)))");
if (Opts.Static)
- Define(Defs, "__STATIC__");
+ Builder.defineMacro("__STATIC__");
else
- Define(Defs, "__DYNAMIC__");
+ Builder.defineMacro("__DYNAMIC__");
if (Opts.POSIXThreads)
- Define(Defs, "_REENTRANT", "1");
+ Builder.defineMacro("_REENTRANT");
}
-static void getDarwinOSXDefines(std::vector &Defs,
+static void getDarwinOSXDefines(MacroBuilder &Builder,
const llvm::Triple &Triple) {
if (Triple.getOS() != llvm::Triple::Darwin)
return;
@@ -129,10 +116,11 @@ static void getDarwinOSXDefines(std::vector &Defs,
// Handle minor version: 10.4.9 -> darwin8.9 -> "1049"
// Cap 10.4.11 -> darwin8.11 -> "1049"
MacOSXStr[3] = std::min(Min, 9U)+'0';
- Define(Defs, "__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", MacOSXStr);
+ Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__",
+ MacOSXStr);
}
-static void getDarwinIPhoneOSDefines(std::vector &Defs,
+static void getDarwinIPhoneOSDefines(MacroBuilder &Builder,
const llvm::Triple &Triple) {
if (Triple.getOS() != llvm::Triple::Darwin)
return;
@@ -151,8 +139,8 @@ static void getDarwinIPhoneOSDefines(std::vector &Defs,
// Handle minor version: 2.2 -> darwin9.2.2 -> 20200
iPhoneOSStr[2] = std::min(Rev, 9U)+'0';
- Define(Defs, "__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__",
- iPhoneOSStr);
+ Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__",
+ iPhoneOSStr);
}
namespace {
@@ -160,9 +148,9 @@ template
class DarwinTargetInfo : public OSTargetInfo {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- std::vector &Defines) const {
- getDarwinDefines(Defines, Opts);
- getDarwinOSXDefines(Defines, Triple);
+ MacroBuilder &Builder) const {
+ getDarwinDefines(Builder, Opts);
+ getDarwinOSXDefines(Builder, Triple);
}
public:
@@ -190,14 +178,14 @@ template
class DragonFlyBSDTargetInfo : public OSTargetInfo {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- std::vector &Defs) const {
+ MacroBuilder &Builder) const {
// DragonFly defines; list based off of gcc output
- Define(Defs, "__DragonFly__");
- Define(Defs, "__DragonFly_cc_version", "100001");
- Define(Defs, "__ELF__");
- Define(Defs, "__KPRINTF_ATTRIBUTE__");
- Define(Defs, "__tune_i386__");
- DefineStd(Defs, "unix", Opts);
+ Builder.defineMacro("__DragonFly__");
+ Builder.defineMacro("__DragonFly_cc_version", "100001");
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
+ Builder.defineMacro("__tune_i386__");
+ DefineStd(Builder, "unix", Opts);
}
public:
DragonFlyBSDTargetInfo(const std::string &triple)
@@ -209,7 +197,7 @@ template
class FreeBSDTargetInfo : public OSTargetInfo {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- std::vector &Defs) const {
+ MacroBuilder &Builder) const {
// FreeBSD defines; list based off of gcc output
// FIXME: Move version number handling to llvm::Triple.
@@ -221,11 +209,11 @@ protected:
char version[] = "X00001";
version[0] = FreeBSD[0];
- Define(Defs, "__FreeBSD__", release);
- Define(Defs, "__FreeBSD_cc_version", version);
- Define(Defs, "__KPRINTF_ATTRIBUTE__");
- DefineStd(Defs, "unix", Opts);
- Define(Defs, "__ELF__", "1");
+ Builder.defineMacro("__FreeBSD__", release);
+ Builder.defineMacro("__FreeBSD_cc_version", version);
+ Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
}
public:
FreeBSDTargetInfo(const std::string &triple)
@@ -239,14 +227,14 @@ template
class LinuxTargetInfo : public OSTargetInfo {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- std::vector &Defs) const {
+ MacroBuilder &Builder) const {
// Linux defines; list based off of gcc output
- DefineStd(Defs, "unix", Opts);
- DefineStd(Defs, "linux", Opts);
- Define(Defs, "__gnu_linux__");
- Define(Defs, "__ELF__", "1");
+ DefineStd(Builder, "unix", Opts);
+ DefineStd(Builder, "linux", Opts);
+ Builder.defineMacro("__gnu_linux__");
+ Builder.defineMacro("__ELF__");
if (Opts.POSIXThreads)
- Define(Defs, "_REENTRANT", "1");
+ Builder.defineMacro("_REENTRANT");
}
public:
LinuxTargetInfo(const std::string& triple)
@@ -260,13 +248,13 @@ template
class NetBSDTargetInfo : public OSTargetInfo {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- std::vector &Defs) const {
+ MacroBuilder &Builder) const {
// NetBSD defines; list based off of gcc output
- Define(Defs, "__NetBSD__", "1");
- Define(Defs, "__unix__", "1");
- Define(Defs, "__ELF__", "1");
+ Builder.defineMacro("__NetBSD__");
+ Builder.defineMacro("__unix__");
+ Builder.defineMacro("__ELF__");
if (Opts.POSIXThreads)
- Define(Defs, "_POSIX_THREADS", "1");
+ Builder.defineMacro("_POSIX_THREADS");
}
public:
NetBSDTargetInfo(const std::string &triple)
@@ -280,14 +268,14 @@ template
class OpenBSDTargetInfo : public OSTargetInfo {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- std::vector &Defs) const {
+ MacroBuilder &Builder) const {
// OpenBSD defines; list based off of gcc output
- Define(Defs, "__OpenBSD__", "1");
- DefineStd(Defs, "unix", Opts);
- Define(Defs, "__ELF__", "1");
+ Builder.defineMacro("__OpenBSD__");
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
if (Opts.POSIXThreads)
- Define(Defs, "_POSIX_THREADS", "1");
+ Builder.defineMacro("_POSIX_THREADS");
}
public:
OpenBSDTargetInfo(const std::string &triple)
@@ -299,12 +287,12 @@ template
class PSPTargetInfo : public OSTargetInfo {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- std::vector &Defs) const {
+ MacroBuilder &Builder) const {
// PSP defines; list based on the output of the pspdev gcc toolchain.
- Define(Defs, "PSP", "1");
- Define(Defs, "_PSP", "1");
- Define(Defs, "__psp__", "1");
- Define(Defs, "__ELF__", "1");
+ Builder.defineMacro("PSP");
+ Builder.defineMacro("_PSP");
+ Builder.defineMacro("__psp__");
+ Builder.defineMacro("__ELF__");
}
public:
PSPTargetInfo(const std::string& triple)
@@ -318,12 +306,12 @@ template
class PS3PPUTargetInfo : public OSTargetInfo {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- std::vector &Defs) const {
+ MacroBuilder &Builder) const {
// PS3 PPU defines.
- Define(Defs, "__PPU__", "1");
- Define(Defs, "__CELLOS_LV2__", "1");
- Define(Defs, "__ELF__", "1");
- Define(Defs, "__LP32__", "1");
+ Builder.defineMacro("__PPU__");
+ Builder.defineMacro("__CELLOS_LV2__");
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__LP32__");
}
public:
PS3PPUTargetInfo(const std::string& triple)
@@ -340,10 +328,10 @@ template
class PS3SPUTargetInfo : public OSTargetInfo {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- std::vector &Defs) const {
+ MacroBuilder &Builder) const {
// PS3 PPU defines.
- Define(Defs, "__SPU__", "1");
- Define(Defs, "__ELF__", "1");
+ Builder.defineMacro("__SPU__");
+ Builder.defineMacro("__ELF__");
}
public:
PS3SPUTargetInfo(const std::string& triple)
@@ -357,12 +345,12 @@ template
class AuroraUXTargetInfo : public OSTargetInfo {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- std::vector &Defs) const {
- DefineStd(Defs, "sun", Opts);
- DefineStd(Defs, "unix", Opts);
- Define(Defs, "__ELF__");
- Define(Defs, "__svr4__");
- Define(Defs, "__SVR4");
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "sun", Opts);
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__svr4__");
+ Builder.defineMacro("__SVR4");
}
public:
AuroraUXTargetInfo(const std::string& triple)
@@ -378,12 +366,12 @@ template
class SolarisTargetInfo : public OSTargetInfo {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- std::vector &Defs) const {
- DefineStd(Defs, "sun", Opts);
- DefineStd(Defs, "unix", Opts);
- Define(Defs, "__ELF__");
- Define(Defs, "__svr4__");
- Define(Defs, "__SVR4");
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "sun", Opts);
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__svr4__");
+ Builder.defineMacro("__SVR4");
}
public:
SolarisTargetInfo(const std::string& triple)
@@ -416,7 +404,7 @@ public:
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const;
+ MacroBuilder &Builder) const;
virtual const char *getVAListDeclaration() const {
return "typedef char* __builtin_va_list;";
@@ -460,34 +448,34 @@ const Builtin::Info PPCTargetInfo::BuiltinInfo[] = {
/// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific
/// #defines that are not tied to a specific subtarget.
void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
- std::vector &Defs) const {
+ MacroBuilder &Builder) const {
// Target identification.
- Define(Defs, "__ppc__");
- Define(Defs, "_ARCH_PPC");
- Define(Defs, "__POWERPC__");
+ Builder.defineMacro("__ppc__");
+ Builder.defineMacro("_ARCH_PPC");
+ Builder.defineMacro("__POWERPC__");
if (PointerWidth == 64) {
- Define(Defs, "_ARCH_PPC64");
- Define(Defs, "_LP64");
- Define(Defs, "__LP64__");
- Define(Defs, "__ppc64__");
+ Builder.defineMacro("_ARCH_PPC64");
+ Builder.defineMacro("_LP64");
+ Builder.defineMacro("__LP64__");
+ Builder.defineMacro("__ppc64__");
} else {
- Define(Defs, "__ppc__");
+ Builder.defineMacro("__ppc__");
}
// Target properties.
- Define(Defs, "_BIG_ENDIAN");
- Define(Defs, "__BIG_ENDIAN__");
+ Builder.defineMacro("_BIG_ENDIAN");
+ Builder.defineMacro("__BIG_ENDIAN__");
// Subtarget options.
- Define(Defs, "__NATURAL_ALIGNMENT__");
- Define(Defs, "__REGISTER_PREFIX__", "");
+ Builder.defineMacro("__NATURAL_ALIGNMENT__");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
// FIXME: Should be controlled by command line option.
- Define(Defs, "__LONG_DOUBLE_128__");
+ Builder.defineMacro("__LONG_DOUBLE_128__");
if (Opts.AltiVec) {
- Define(Defs, "__VEC__", "10206");
- Define(Defs, "__ALTIVEC__", "1");
+ Builder.defineMacro("__VEC__", "10206");
+ Builder.defineMacro("__ALTIVEC__");
}
}
@@ -682,7 +670,7 @@ public:
return "~{dirflag},~{fpsr},~{flags}";
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const;
+ MacroBuilder &Builder) const;
virtual bool setFeatureEnabled(llvm::StringMap &Features,
const std::string &Name,
bool Enabled) const;
@@ -828,51 +816,51 @@ void X86TargetInfo::HandleTargetFeatures(std::vector &Features) {
/// X86TargetInfo::getTargetDefines - Return a set of the X86-specific #defines
/// that are not tied to a specific subtarget.
void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
- std::vector &Defs) const {
+ MacroBuilder &Builder) const {
// Target identification.
if (PointerWidth == 64) {
- Define(Defs, "_LP64");
- Define(Defs, "__LP64__");
- Define(Defs, "__amd64__");
- Define(Defs, "__amd64");
- Define(Defs, "__x86_64");
- Define(Defs, "__x86_64__");
+ Builder.defineMacro("_LP64");
+ Builder.defineMacro("__LP64__");
+ Builder.defineMacro("__amd64__");
+ Builder.defineMacro("__amd64");
+ Builder.defineMacro("__x86_64");
+ Builder.defineMacro("__x86_64__");
} else {
- DefineStd(Defs, "i386", Opts);
+ DefineStd(Builder, "i386", Opts);
}
// Target properties.
- Define(Defs, "__LITTLE_ENDIAN__");
+ Builder.defineMacro("__LITTLE_ENDIAN__");
// Subtarget options.
- Define(Defs, "__nocona");
- Define(Defs, "__nocona__");
- Define(Defs, "__tune_nocona__");
- Define(Defs, "__REGISTER_PREFIX__", "");
+ Builder.defineMacro("__nocona");
+ Builder.defineMacro("__nocona__");
+ Builder.defineMacro("__tune_nocona__");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
// Define __NO_MATH_INLINES on linux/x86 so that we don't get inline
// functions in glibc header files that use FP Stack inline asm which the
// backend can't deal with (PR879).
- Define(Defs, "__NO_MATH_INLINES");
+ Builder.defineMacro("__NO_MATH_INLINES");
// Each case falls through to the previous one here.
switch (SSELevel) {
case SSE42:
- Define(Defs, "__SSE4_2__");
+ Builder.defineMacro("__SSE4_2__");
case SSE41:
- Define(Defs, "__SSE4_1__");
+ Builder.defineMacro("__SSE4_1__");
case SSSE3:
- Define(Defs, "__SSSE3__");
+ Builder.defineMacro("__SSSE3__");
case SSE3:
- Define(Defs, "__SSE3__");
+ Builder.defineMacro("__SSE3__");
case SSE2:
- Define(Defs, "__SSE2__");
- Define(Defs, "__SSE2_MATH__"); // -mfp-math=sse always implied.
+ Builder.defineMacro("__SSE2__");
+ Builder.defineMacro("__SSE2_MATH__"); // -mfp-math=sse always implied.
case SSE1:
- Define(Defs, "__SSE__");
- Define(Defs, "__SSE_MATH__"); // -mfp-math=sse always implied.
+ Builder.defineMacro("__SSE__");
+ Builder.defineMacro("__SSE_MATH__"); // -mfp-math=sse always implied.
case MMX:
- Define(Defs, "__MMX__");
+ Builder.defineMacro("__MMX__");
case NoMMXSSE:
break;
}
@@ -999,13 +987,13 @@ public:
"v128:128:128-a0:0:64-f80:32:32-n8:16:32";
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- X86_32TargetInfo::getTargetDefines(Opts, Defines);
+ MacroBuilder &Builder) const {
+ X86_32TargetInfo::getTargetDefines(Opts, Builder);
// This list is based off of the the list of things MingW defines
- Define(Defines, "_WIN32");
- DefineStd(Defines, "WIN32", Opts);
- DefineStd(Defines, "WINNT", Opts);
- Define(Defines, "_X86_");
+ Builder.defineMacro("_WIN32");
+ DefineStd(Builder, "WIN32", Opts);
+ DefineStd(Builder, "WINNT", Opts);
+ Builder.defineMacro("_X86_");
}
};
} // end anonymous namespace
@@ -1019,12 +1007,12 @@ public:
: WindowsX86_32TargetInfo(triple) {
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- WindowsX86_32TargetInfo::getTargetDefines(Opts, Defines);
+ MacroBuilder &Builder) const {
+ WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
// The value of the following reflects processor type.
// 300=386, 400=486, 500=Pentium, 600=Blend (default)
// We lost the original triple, so we use the default.
- Define(Defines, "_M_IX86", "600");
+ Builder.defineMacro("_M_IX86", "600");
}
};
} // end anonymous namespace
@@ -1037,11 +1025,11 @@ public:
: WindowsX86_32TargetInfo(triple) {
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- WindowsX86_32TargetInfo::getTargetDefines(Opts, Defines);
- Define(Defines, "__MSVCRT__");
- Define(Defines, "__MINGW32__");
- Define(Defines, "__declspec", "__declspec");
+ MacroBuilder &Builder) const {
+ WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__MSVCRT__");
+ Builder.defineMacro("__MINGW32__");
+ Builder.defineMacro("__declspec", "__declspec");
}
};
} // end anonymous namespace
@@ -1060,11 +1048,11 @@ public:
"a0:0:64-f80:32:32-n8:16:32";
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- X86_32TargetInfo::getTargetDefines(Opts, Defines);
- Define(Defines, "__CYGWIN__");
- Define(Defines, "__CYGWIN32__");
- DefineStd(Defines, "unix", Opts);
+ MacroBuilder &Builder) const {
+ X86_32TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__CYGWIN__");
+ Builder.defineMacro("__CYGWIN32__");
+ DefineStd(Builder, "unix", Opts);
}
};
} // end anonymous namespace
@@ -1116,10 +1104,10 @@ public:
DoubleAlign = LongLongAlign = 64;
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- X86_64TargetInfo::getTargetDefines(Opts, Defines);
- Define(Defines, "_WIN64");
- DefineStd(Defines, "WIN64", Opts);
+ MacroBuilder &Builder) const {
+ X86_64TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("_WIN64");
+ DefineStd(Builder, "WIN64", Opts);
}
};
} // end anonymous namespace
@@ -1132,9 +1120,9 @@ public:
: WindowsX86_64TargetInfo(triple) {
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- WindowsX86_64TargetInfo::getTargetDefines(Opts, Defines);
- Define(Defines, "_M_X64");
+ MacroBuilder &Builder) const {
+ WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("_M_X64");
}
virtual const char *getVAListDeclaration() const {
return "typedef char* va_list;";
@@ -1150,11 +1138,11 @@ public:
: WindowsX86_64TargetInfo(triple) {
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- WindowsX86_64TargetInfo::getTargetDefines(Opts, Defines);
- Define(Defines, "__MSVCRT__");
- Define(Defines, "__MINGW64__");
- Define(Defines, "__declspec");
+ MacroBuilder &Builder) const {
+ WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__MSVCRT__");
+ Builder.defineMacro("__MINGW64__");
+ Builder.defineMacro("__declspec");
}
};
} // end anonymous namespace
@@ -1342,61 +1330,58 @@ public:
return true;
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defs) const {
+ MacroBuilder &Builder) const {
// Target identification.
- Define(Defs, "__arm");
- Define(Defs, "__arm__");
+ Builder.defineMacro("__arm");
+ Builder.defineMacro("__arm__");
// Target properties.
- Define(Defs, "__ARMEL__");
- Define(Defs, "__LITTLE_ENDIAN__");
- Define(Defs, "__REGISTER_PREFIX__", "");
+ Builder.defineMacro("__ARMEL__");
+ Builder.defineMacro("__LITTLE_ENDIAN__");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
llvm::StringRef CPUArch = getCPUDefineSuffix(CPU);
- std::string ArchName = "__ARM_ARCH_";
- ArchName += CPUArch;
- ArchName += "__";
- Define(Defs, ArchName);
+ Builder.defineMacro("__ARM_ARCH_" + CPUArch + "__");
// Subtarget options.
// FIXME: It's more complicated than this and we don't really support
// interworking.
if ('5' <= CPUArch[0] && CPUArch[0] <= '7')
- Define(Defs, "__THUMB_INTERWORK__");
+ Builder.defineMacro("__THUMB_INTERWORK__");
if (ABI == "aapcs" || ABI == "aapcs-linux")
- Define(Defs, "__ARM_EABI__");
+ Builder.defineMacro("__ARM_EABI__");
if (SoftFloat)
- Define(Defs, "__SOFTFP__");
+ Builder.defineMacro("__SOFTFP__");
if (CPU == "xscale")
- Define(Defs, "__XSCALE__");
+ Builder.defineMacro("__XSCALE__");
bool IsThumb2 = IsThumb && (CPUArch == "6T2" || CPUArch.startswith("7"));
if (IsThumb) {
- Define(Defs, "__THUMBEL__");
- Define(Defs, "__thumb__");
+ Builder.defineMacro("__THUMBEL__");
+ Builder.defineMacro("__thumb__");
if (IsThumb2)
- Define(Defs, "__thumb2__");
+ Builder.defineMacro("__thumb2__");
}
// Note, this is always on in gcc, even though it doesn't make sense.
- Define(Defs, "__APCS_32__");
+ Builder.defineMacro("__APCS_32__");
if (FPUModeIsVFP((FPUMode) FPU))
- Define(Defs, "__VFP_FP__");
+ Builder.defineMacro("__VFP_FP__");
// This only gets set when Neon instructions are actually available, unlike
// the VFP define, hence the soft float and arch check. This is subtly
// different from gcc, we follow the intent which was that it should be set
// when Neon instructions are actually available.
if (FPU == NeonFPU && !SoftFloat && IsThumb2)
- Define(Defs, "__ARM_NEON__");
+ Builder.defineMacro("__ARM_NEON__");
if (getTriple().getOS() == llvm::Triple::Darwin)
- Define(Defs, "__USING_SJLJ_EXCEPTIONS__");
+ Builder.defineMacro("__USING_SJLJ_EXCEPTIONS__");
}
virtual void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const {
@@ -1475,9 +1460,9 @@ class DarwinARMTargetInfo :
public DarwinTargetInfo {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- std::vector &Defines) const {
- getDarwinDefines(Defines, Opts);
- getDarwinIPhoneOSDefines(Defines, Triple);
+ MacroBuilder &Builder) const {
+ getDarwinDefines(Builder, Opts);
+ getDarwinIPhoneOSDefines(Builder, Triple);
}
public:
@@ -1497,10 +1482,10 @@ public:
"i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32";
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- DefineStd(Defines, "sparc", Opts);
- Define(Defines, "__sparcv8");
- Define(Defines, "__REGISTER_PREFIX__", "");
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "sparc", Opts);
+ Builder.defineMacro("__sparcv8");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
}
virtual void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const {
@@ -1630,18 +1615,18 @@ namespace {
virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { return 16; }
virtual uint64_t getPointerAlignV(unsigned AddrSpace) const { return 8; }
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- Define(Defines, "__pic16");
- Define(Defines, "rom", "__attribute__((address_space(1)))");
- Define(Defines, "ram", "__attribute__((address_space(0)))");
- Define(Defines, "_section(SectName)",
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__pic16");
+ Builder.defineMacro("rom", "__attribute__((address_space(1)))");
+ Builder.defineMacro("ram", "__attribute__((address_space(0)))");
+ Builder.defineMacro("_section(SectName)",
"__attribute__((section(SectName)))");
- Define(Defines, "near",
+ Builder.defineMacro("near",
"__attribute__((section(\"Address=NEAR\")))");
- Define(Defines, "_address(Addr)",
+ Builder.defineMacro("_address(Addr)",
"__attribute__((section(\"Address=\"#Addr)))");
- Define(Defines, "_CONFIG(conf)", "asm(\"CONFIG \"#conf)");
- Define(Defines, "_interrupt",
+ Builder.defineMacro("_CONFIG(conf)", "asm(\"CONFIG \"#conf)");
+ Builder.defineMacro("_interrupt",
"__attribute__((section(\"interrupt=0x4\"))) \
__attribute__((used))");
}
@@ -1672,7 +1657,8 @@ namespace {
MSP430TargetInfo(const std::string& triple) : TargetInfo(triple) {
TLSSupported = false;
IntWidth = 16;
- LongWidth = LongLongWidth = 32;
+ LongWidth = 32;
+ LongLongWidth = 64;
PointerWidth = 16;
IntAlign = 8;
LongAlign = LongLongAlign = 8;
@@ -1686,9 +1672,9 @@ namespace {
DescriptionString = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16";
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- Define(Defines, "MSP430");
- Define(Defines, "__MSP430__");
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("MSP430");
+ Builder.defineMacro("__MSP430__");
// FIXME: defines for different 'flavours' of MCU
}
virtual void getTargetBuiltins(const Builtin::Info *&Records,
@@ -1746,9 +1732,9 @@ namespace {
"i64:64:64-f32:32:32-f64:64:64-f128:128:128-a0:16:16-n32:64";
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- Define(Defines, "__s390__");
- Define(Defines, "__s390x__");
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__s390__");
+ Builder.defineMacro("__s390x__");
}
virtual void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const {
@@ -1805,12 +1791,12 @@ namespace {
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- DefineStd(Defines, "bfin", Opts);
- DefineStd(Defines, "BFIN", Opts);
- Define(Defines, "__ADSPBLACKFIN__");
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "bfin", Opts);
+ DefineStd(Builder, "BFIN", Opts);
+ Builder.defineMacro("__ADSPBLACKFIN__");
// FIXME: This one is really dependent on -mcpu
- Define(Defines, "__ADSPLPBLACKFIN__");
+ Builder.defineMacro("__ADSPLPBLACKFIN__");
// FIXME: Add cpu-dependent defines and __SILICON_REVISION__
}
@@ -1906,10 +1892,10 @@ namespace {
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- DefineStd(Defines, "tce", Opts);
- Define(Defines, "__TCE__");
- Define(Defines, "__TCE_V1__");
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "tce", Opts);
+ Builder.defineMacro("__TCE__");
+ Builder.defineMacro("__TCE_V1__");
}
virtual void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const {}
@@ -1940,12 +1926,12 @@ public:
"i64:32:64-f32:32:32-f64:64:64-v64:64:64-n32";
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- DefineStd(Defines, "mips", Opts);
- Define(Defines, "_mips");
- DefineStd(Defines, "MIPSEB", Opts);
- Define(Defines, "_MIPSEB");
- Define(Defines, "__REGISTER_PREFIX__", "");
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "mips", Opts);
+ Builder.defineMacro("_mips");
+ DefineStd(Builder, "MIPSEB", Opts);
+ Builder.defineMacro("_MIPSEB");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
}
virtual void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const {
@@ -2047,16 +2033,16 @@ public:
}
virtual void getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const;
+ MacroBuilder &Builder) const;
};
void MipselTargetInfo::getTargetDefines(const LangOptions &Opts,
- std::vector &Defines) const {
- DefineStd(Defines, "mips", Opts);
- Define(Defines, "_mips");
- DefineStd(Defines, "MIPSEL", Opts);
- Define(Defines, "_MIPSEL");
- Define(Defines, "__REGISTER_PREFIX__", "");
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "mips", Opts);
+ Builder.defineMacro("_mips");
+ DefineStd(Builder, "MIPSEL", Opts);
+ Builder.defineMacro("_MIPSEL");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
}
} // end anonymous namespace.
@@ -2171,6 +2157,8 @@ static TargetInfo *AllocateTarget(const std::string &T) {
return new DarwinX86_64TargetInfo(T);
case llvm::Triple::Linux:
return new LinuxTargetInfo(T);
+ case llvm::Triple::DragonFly:
+ return new DragonFlyBSDTargetInfo(T);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo(T);
case llvm::Triple::OpenBSD:
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 1bece7fec6fa7..1fa422f29e1cf 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -24,7 +24,7 @@ using namespace clang;
using namespace CodeGen;
llvm::Constant *CodeGenFunction::
-BuildDescriptorBlockDecl(bool BlockHasCopyDispose, uint64_t Size,
+BuildDescriptorBlockDecl(bool BlockHasCopyDispose, CharUnits Size,
const llvm::StructType* Ty,
std::vector *NoteForHelper) {
const llvm::Type *UnsignedLongTy
@@ -40,7 +40,7 @@ BuildDescriptorBlockDecl(bool BlockHasCopyDispose, uint64_t Size,
// FIXME: What is the right way to say this doesn't fit? We should give
// a user diagnostic in that case. Better fix would be to change the
// API to size_t.
- C = llvm::ConstantInt::get(UnsignedLongTy, Size);
+ C = llvm::ConstantInt::get(UnsignedLongTy, Size.getQuantity());
Elts.push_back(C);
if (BlockHasCopyDispose) {
@@ -176,7 +176,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
// We run this first so that we set BlockHasCopyDispose from the entire
// block literal.
// __invoke
- uint64_t subBlockSize, subBlockAlign;
+ CharUnits subBlockSize;
+ uint64_t subBlockAlign;
llvm::SmallVector subBlockDeclRefDecls;
bool subBlockHasCopyDispose = false;
llvm::Function *Fn
@@ -321,13 +322,13 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
// compared to gcc by not grabbing the forwarding slot as this must
// be done during Block_copy for us, and we can postpone the work
// until then.
- uint64_t offset = BlockDecls[BDRE->getDecl()];
+ CharUnits offset = BlockDecls[BDRE->getDecl()];
llvm::Value *BlockLiteral = LoadBlockStruct();
Loc = Builder.CreateGEP(BlockLiteral,
llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
- offset),
+ offset.getQuantity()),
"block.literal");
Ty = llvm::PointerType::get(Ty, 0);
Loc = Builder.CreateBitCast(Loc, Ty);
@@ -513,12 +514,12 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E,
return EmitCall(FnInfo, Func, ReturnValue, Args);
}
-uint64_t CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) {
+CharUnits CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) {
const ValueDecl *VD = E->getDecl();
- uint64_t &offset = BlockDecls[VD];
+ CharUnits &offset = BlockDecls[VD];
// See if we have already allocated an offset for this variable.
- if (offset)
+ if (offset.isPositive())
return offset;
// Don't run the expensive check, unless we have to.
@@ -535,13 +536,13 @@ uint64_t CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) {
llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
const ValueDecl *VD = E->getDecl();
- uint64_t offset = AllocateBlockDecl(E);
+ CharUnits offset = AllocateBlockDecl(E);
llvm::Value *BlockLiteral = LoadBlockStruct();
llvm::Value *V = Builder.CreateGEP(BlockLiteral,
llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
- offset),
+ offset.getQuantity()),
"block.literal");
if (E->isByRef()) {
const llvm::Type *PtrStructTy
@@ -594,10 +595,10 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
// Block literal size. For global blocks we just use the size of the generic
// block literal struct.
- uint64_t BlockLiteralSize =
- TheTargetData.getTypeStoreSizeInBits(getGenericBlockLiteralType()) / 8;
+ CharUnits BlockLiteralSize = CharUnits::fromQuantity(
+ TheTargetData.getTypeStoreSizeInBits(getGenericBlockLiteralType()) / 8);
DescriptorFields[1] =
- llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize);
+ llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize.getQuantity());
llvm::Constant *DescriptorStruct =
llvm::ConstantStruct::get(VMContext, &DescriptorFields[0], 2, false);
@@ -615,7 +616,8 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
std::vector LiteralFields(FieldCount);
CodeGenFunction::BlockInfo Info(0, n);
- uint64_t subBlockSize, subBlockAlign;
+ CharUnits subBlockSize;
+ uint64_t subBlockAlign;
llvm::SmallVector subBlockDeclRefDecls;
bool subBlockHasCopyDispose = false;
llvm::DenseMap LocalDeclMap;
@@ -677,7 +679,7 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
const BlockInfo& Info,
const Decl *OuterFuncDecl,
llvm::DenseMap ldm,
- uint64_t &Size,
+ CharUnits &Size,
uint64_t &Align,
llvm::SmallVector &subBlockDeclRefDecls,
bool &subBlockHasCopyDispose) {
@@ -698,8 +700,9 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
LocalDeclMap[VD] = i->second;
}
- BlockOffset = CGM.getTargetData()
- .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8;
+ BlockOffset = CharUnits::fromQuantity(
+ CGM.getTargetData()
+ .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8);
BlockAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
const FunctionType *BlockFunctionType = BExpr->getFunctionType();
@@ -799,7 +802,8 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
// The runtime needs a minimum alignment of a void *.
uint64_t MinAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
- BlockOffset = llvm::RoundUpToAlignment(BlockOffset, MinAlign);
+ BlockOffset = CharUnits::fromQuantity(
+ llvm::RoundUpToAlignment(BlockOffset.getQuantity(), MinAlign));
Size = BlockOffset;
Align = BlockAlign;
@@ -808,30 +812,32 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
return Fn;
}
-uint64_t BlockFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) {
+CharUnits BlockFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) {
const ValueDecl *D = dyn_cast(BDRE->getDecl());
- uint64_t Size = getContext().getTypeSize(D->getType()) / 8;
+ CharUnits Size = getContext().getTypeSizeInChars(D->getType());
uint64_t Align = getContext().getDeclAlignInBytes(D);
if (BDRE->isByRef()) {
- Size = getContext().getTypeSize(getContext().VoidPtrTy) / 8;
+ Size = getContext().getTypeSizeInChars(getContext().VoidPtrTy);
Align = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
}
assert ((Align > 0) && "alignment must be 1 byte or more");
- uint64_t OldOffset = BlockOffset;
+ CharUnits OldOffset = BlockOffset;
// Ensure proper alignment, even if it means we have to have a gap
- BlockOffset = llvm::RoundUpToAlignment(BlockOffset, Align);
+ BlockOffset = CharUnits::fromQuantity(
+ llvm::RoundUpToAlignment(BlockOffset.getQuantity(), Align));
BlockAlign = std::max(Align, BlockAlign);
- uint64_t Pad = BlockOffset - OldOffset;
- if (Pad) {
- llvm::ArrayType::get(llvm::Type::getInt8Ty(VMContext), Pad);
+ CharUnits Pad = BlockOffset - OldOffset;
+ if (Pad.isPositive()) {
+ llvm::ArrayType::get(llvm::Type::getInt8Ty(VMContext), Pad.getQuantity());
QualType PadTy = getContext().getConstantArrayType(getContext().CharTy,
- llvm::APInt(32, Pad),
+ llvm::APInt(32,
+ Pad.getQuantity()),
ArrayType::Normal, 0);
ValueDecl *PadDecl = VarDecl::Create(getContext(), 0, SourceLocation(),
0, QualType(PadTy), 0, VarDecl::None);
diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h
index 38e02a70a4e25..f42244c52e0ef 100644
--- a/lib/CodeGen/CGBlocks.h
+++ b/lib/CodeGen/CGBlocks.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
@@ -175,13 +176,13 @@ public:
/// BlockOffset - The offset in bytes for the next allocation of an
/// imported block variable.
- uint64_t BlockOffset;
+ CharUnits BlockOffset;
/// BlockAlign - Maximal alignment needed for the Block expressed in bytes.
uint64_t BlockAlign;
/// getBlockOffset - Allocate an offset for the ValueDecl from a
/// BlockDeclRefExpr in a block literal (BlockExpr).
- uint64_t getBlockOffset(const BlockDeclRefExpr *E);
+ CharUnits getBlockOffset(const BlockDeclRefExpr *E);
/// BlockHasCopyDispose - True iff the block uses copy/dispose.
bool BlockHasCopyDispose;
@@ -191,7 +192,7 @@ public:
llvm::SmallVector BlockDeclRefDecls;
/// BlockDecls - Offsets for all Decls in BlockDeclRefExprs.
- std::map BlockDecls;
+ std::map