Date: Sun, 19 Aug 2012 10:33:05 +0000 (UTC) From: Dimitry Andric <dim@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org Subject: svn commit: r239392 - in vendor/clang/dist: docs docs/analyzer include/clang/AST include/clang/ASTMatchers include/clang/Basic include/clang/Lex include/clang/Parse include/clang/Sema include/clang... Message-ID: <201208191033.q7JAX5KX070368@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dim Date: Sun Aug 19 10:33:04 2012 New Revision: 239392 URL: http://svn.freebsd.org/changeset/base/239392 Log: Vendor import of clang trunk r162107: http://llvm.org/svn/llvm-project/cfe/trunk@162107 Added: vendor/clang/dist/docs/analyzer/ vendor/clang/dist/docs/analyzer/IPA.txt vendor/clang/dist/test/Analysis/inlining/dyn-dispatch-bifurcate.cpp vendor/clang/dist/test/Analysis/reinterpret-cast.cpp vendor/clang/dist/test/CodeGen/align-global-large.c vendor/clang/dist/test/CodeGen/arm-neon-misc.c vendor/clang/dist/test/CodeGen/complex-builtints.c vendor/clang/dist/test/CodeGenOpenCL/vectorLoadStore.cl vendor/clang/dist/test/Index/complete-preamble.cpp vendor/clang/dist/test/Index/complete-preamble.h vendor/clang/dist/test/Sema/arm-asm.c vendor/clang/dist/test/Sema/warn-type-safety-mpi-hdf5.c vendor/clang/dist/test/Sema/warn-type-safety.c vendor/clang/dist/test/Sema/warn-type-safety.cpp vendor/clang/dist/test/SemaObjC/warn-cast-of-sel-expr.m vendor/clang/dist/test/SemaObjCXX/abstract-class-type-ivar.mm Modified: vendor/clang/dist/docs/LanguageExtensions.html vendor/clang/dist/docs/ReleaseNotes.html vendor/clang/dist/include/clang/AST/ASTContext.h vendor/clang/dist/include/clang/AST/Attr.h vendor/clang/dist/include/clang/AST/CommentCommandTraits.h vendor/clang/dist/include/clang/AST/DeclBase.h vendor/clang/dist/include/clang/AST/DeclCXX.h vendor/clang/dist/include/clang/AST/DeclGroup.h vendor/clang/dist/include/clang/AST/DeclLookups.h vendor/clang/dist/include/clang/AST/PrettyPrinter.h vendor/clang/dist/include/clang/AST/RawCommentList.h vendor/clang/dist/include/clang/AST/Stmt.h vendor/clang/dist/include/clang/AST/TemplateBase.h vendor/clang/dist/include/clang/AST/TypeLoc.h vendor/clang/dist/include/clang/ASTMatchers/ASTMatchers.h vendor/clang/dist/include/clang/Basic/Attr.td vendor/clang/dist/include/clang/Basic/Builtins.def vendor/clang/dist/include/clang/Basic/DiagnosticGroups.td vendor/clang/dist/include/clang/Basic/DiagnosticParseKinds.td vendor/clang/dist/include/clang/Basic/DiagnosticSemaKinds.td vendor/clang/dist/include/clang/Lex/PTHManager.h vendor/clang/dist/include/clang/Parse/Parser.h vendor/clang/dist/include/clang/Sema/AttributeList.h vendor/clang/dist/include/clang/Sema/Sema.h vendor/clang/dist/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h vendor/clang/dist/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h vendor/clang/dist/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h vendor/clang/dist/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h vendor/clang/dist/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h vendor/clang/dist/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h vendor/clang/dist/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h vendor/clang/dist/lib/AST/APValue.cpp vendor/clang/dist/lib/AST/ASTContext.cpp vendor/clang/dist/lib/AST/ASTDiagnostic.cpp vendor/clang/dist/lib/AST/CommentCommandTraits.cpp vendor/clang/dist/lib/AST/DeclCXX.cpp vendor/clang/dist/lib/AST/DeclPrinter.cpp vendor/clang/dist/lib/AST/DeclTemplate.cpp vendor/clang/dist/lib/AST/DumpXML.cpp vendor/clang/dist/lib/AST/NestedNameSpecifier.cpp vendor/clang/dist/lib/AST/RawCommentList.cpp vendor/clang/dist/lib/AST/Stmt.cpp vendor/clang/dist/lib/AST/StmtPrinter.cpp vendor/clang/dist/lib/AST/TemplateBase.cpp vendor/clang/dist/lib/Basic/Diagnostic.cpp vendor/clang/dist/lib/Basic/Targets.cpp vendor/clang/dist/lib/CodeGen/CGBuiltin.cpp vendor/clang/dist/lib/CodeGen/CGDebugInfo.cpp vendor/clang/dist/lib/CodeGen/CGExpr.cpp vendor/clang/dist/lib/CodeGen/CGExprCXX.cpp vendor/clang/dist/lib/CodeGen/CGStmt.cpp vendor/clang/dist/lib/CodeGen/CGValue.h vendor/clang/dist/lib/Driver/Tools.cpp vendor/clang/dist/lib/Frontend/ASTConsumers.cpp vendor/clang/dist/lib/Frontend/CacheTokens.cpp vendor/clang/dist/lib/Lex/PTHLexer.cpp vendor/clang/dist/lib/Parse/ParseDecl.cpp vendor/clang/dist/lib/Parse/ParseStmt.cpp vendor/clang/dist/lib/Rewrite/RewriteModernObjC.cpp vendor/clang/dist/lib/Rewrite/RewriteObjC.cpp vendor/clang/dist/lib/Sema/AttributeList.cpp vendor/clang/dist/lib/Sema/SemaCast.cpp vendor/clang/dist/lib/Sema/SemaChecking.cpp vendor/clang/dist/lib/Sema/SemaCodeComplete.cpp vendor/clang/dist/lib/Sema/SemaDecl.cpp vendor/clang/dist/lib/Sema/SemaDeclAttr.cpp vendor/clang/dist/lib/Sema/SemaDeclCXX.cpp vendor/clang/dist/lib/Sema/SemaExceptionSpec.cpp vendor/clang/dist/lib/Sema/SemaExpr.cpp vendor/clang/dist/lib/Sema/SemaExprMember.cpp vendor/clang/dist/lib/Sema/SemaOverload.cpp vendor/clang/dist/lib/Sema/SemaStmt.cpp vendor/clang/dist/lib/Sema/SemaTemplate.cpp vendor/clang/dist/lib/Sema/SemaTemplateInstantiate.cpp vendor/clang/dist/lib/Sema/SemaType.cpp vendor/clang/dist/lib/Sema/TreeTransform.h vendor/clang/dist/lib/Serialization/ASTReader.cpp vendor/clang/dist/lib/Serialization/ASTWriter.cpp vendor/clang/dist/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp vendor/clang/dist/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp vendor/clang/dist/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp vendor/clang/dist/lib/StaticAnalyzer/Core/AnalysisManager.cpp vendor/clang/dist/lib/StaticAnalyzer/Core/BugReporter.cpp vendor/clang/dist/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp vendor/clang/dist/lib/StaticAnalyzer/Core/CallEvent.cpp vendor/clang/dist/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp vendor/clang/dist/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp vendor/clang/dist/lib/StaticAnalyzer/Core/PathDiagnostic.cpp vendor/clang/dist/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp vendor/clang/dist/lib/StaticAnalyzer/Core/ProgramState.cpp vendor/clang/dist/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp vendor/clang/dist/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp vendor/clang/dist/test/Analysis/CFNumber.c vendor/clang/dist/test/Analysis/CheckNSError.m vendor/clang/dist/test/Analysis/array-struct.c vendor/clang/dist/test/Analysis/ctor-inlining.mm vendor/clang/dist/test/Analysis/dtor.cpp vendor/clang/dist/test/Analysis/func.c vendor/clang/dist/test/Analysis/html-diags.c vendor/clang/dist/test/Analysis/inline.cpp vendor/clang/dist/test/Analysis/inlining/DynDispatchBifurcate.m vendor/clang/dist/test/Analysis/inlining/InlineObjCClassMethod.m vendor/clang/dist/test/Analysis/keychainAPI.m vendor/clang/dist/test/Analysis/malloc-annotations.c vendor/clang/dist/test/Analysis/malloc.c vendor/clang/dist/test/Analysis/method-call-path-notes.cpp vendor/clang/dist/test/Analysis/method-call.cpp vendor/clang/dist/test/Analysis/misc-ps-region-store.m vendor/clang/dist/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m vendor/clang/dist/test/Analysis/ptr-arith.c vendor/clang/dist/test/Analysis/security-syntax-checks.m vendor/clang/dist/test/Analysis/sizeofpointer.c vendor/clang/dist/test/Analysis/stack-addr-ps.cpp vendor/clang/dist/test/Analysis/stream.c vendor/clang/dist/test/Analysis/variadic-method-types.m vendor/clang/dist/test/CodeCompletion/objc-expr.m vendor/clang/dist/test/CodeGen/alignment.c vendor/clang/dist/test/CodeGen/ms-inline-asm.c vendor/clang/dist/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp vendor/clang/dist/test/CodeGenObjC/instance-method-metadata.m vendor/clang/dist/test/CodeGenObjC/ns_consume_null_check.m vendor/clang/dist/test/Driver/Xlinker-args.c vendor/clang/dist/test/Index/complete-enums.cpp vendor/clang/dist/test/Index/complete-exprs.m vendor/clang/dist/test/Parser/ms-inline-asm.c vendor/clang/dist/test/Sema/128bitint.c vendor/clang/dist/test/Sema/builtins-decl.c vendor/clang/dist/test/Sema/callingconv.c vendor/clang/dist/test/Sema/static-array.c vendor/clang/dist/test/Sema/tentative-decls.c vendor/clang/dist/test/Sema/warn-documentation.cpp vendor/clang/dist/test/SemaCXX/convert-to-bool.cpp vendor/clang/dist/test/SemaCXX/pragma-pack.cpp vendor/clang/dist/test/SemaCXX/references.cpp vendor/clang/dist/test/SemaCXX/uninitialized.cpp vendor/clang/dist/test/SemaCXX/warn-thread-safety-parsing.cpp vendor/clang/dist/test/Tooling/clang-check-ast-dump.cpp vendor/clang/dist/unittests/ASTMatchers/ASTMatchersTest.cpp vendor/clang/dist/unittests/Tooling/RecursiveASTVisitorTest.cpp vendor/clang/dist/utils/TableGen/ClangAttrEmitter.cpp vendor/clang/dist/utils/analyzer/CmpRuns.py vendor/clang/dist/www/comparison.html Modified: vendor/clang/dist/docs/LanguageExtensions.html ============================================================================== --- vendor/clang/dist/docs/LanguageExtensions.html Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/docs/LanguageExtensions.html Sun Aug 19 10:33:04 2012 (r239392) @@ -142,6 +142,13 @@ <li><a href="#ts_slr"><tt>shared_locks_required(...)</tt></a></li> </ul> </li> +<li><a href="#type_safety">Type Safety Checking</a> + <ul> + <li><a href="#argument_with_type_tag"><tt>argument_with_type_tag(...)</tt></a></li> + <li><a href="#pointer_with_type_tag"><tt>pointer_with_type_tag(...)</tt></a></li> + <li><a href="#type_tag_for_datatype"><tt>type_tag_for_datatype(...)</tt></a></li> + </ul> +</li> </ul> <!-- ======================================================================= --> @@ -1913,6 +1920,161 @@ declaration to specify that the function shared locks. Arguments must be lockable type, and there must be at least one argument.</p> +<!-- ======================================================================= --> +<h2 id="type_safety">Type Safety Checking</h2> +<!-- ======================================================================= --> + +<p>Clang supports additional attributes to enable checking type safety +properties that can't be enforced by C type system. Usecases include:</p> +<ul> +<li>MPI library implementations, where these attributes enable checking that + buffer type matches the passed <tt>MPI_Datatype</tt>;</li> +<li>for HDF5 library there is a similar usecase as MPI;</li> +<li>checking types of variadic functions' arguments for functions like + <tt>fcntl()</tt> and <tt>ioctl()</tt>.</li> +</ul> + +<p>You can detect support for these attributes with __has_attribute(). For +example:</p> + +<blockquote> +<pre> +#if defined(__has_attribute) +# if __has_attribute(argument_with_type_tag) && \ + __has_attribute(pointer_with_type_tag) && \ + __has_attribute(type_tag_for_datatype) +# define ATTR_MPI_PWT(buffer_idx, type_idx) __attribute__((pointer_with_type_tag(mpi,buffer_idx,type_idx))) +/* ... other macros ... */ +# endif +#endif + +#if !defined(ATTR_MPI_PWT) +#define ATTR_MPI_PWT(buffer_idx, type_idx) +#endif + +int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */) + ATTR_MPI_PWT(1,3); +</pre> +</blockquote> + +<h3 id="argument_with_type_tag"><tt>argument_with_type_tag(...)</tt></h3> + +<p>Use <tt>__attribute__((argument_with_type_tag(arg_kind, arg_idx, +type_tag_idx)))</tt> on a function declaration to specify that the function +accepts a type tag that determines the type of some other argument. +<tt>arg_kind</tt> is an identifier that should be used when annotating all +applicable type tags.</p> + +<p>This attribute is primarily useful for checking arguments of variadic +functions (<tt>pointer_with_type_tag</tt> can be used in most of non-variadic +cases).</p> + +<p>For example:</p> +<blockquote> +<pre> +int fcntl(int fd, int cmd, ...) + __attribute__(( argument_with_type_tag(fcntl,3,2) )); +</pre> +</blockquote> + +<h3 id="pointer_with_type_tag"><tt>pointer_with_type_tag(...)</tt></h3> + +<p>Use <tt>__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx, +type_tag_idx)))</tt> on a function declaration to specify that the +function a type tag that determines the pointee type of some other pointer +argument.</p> + +<p>For example:</p> +<blockquote> +<pre> +int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */) + __attribute__(( pointer_with_type_tag(mpi,1,3) )); +</pre> +</blockquote> + +<h3 id="type_tag_for_datatype"><tt>type_tag_for_datatype(...)</tt></h3> + +<p>Clang supports annotating type tags of two forms.</p> + +<ul> +<li><b>Type tag that is an expression containing a reference to some declared +identifier.</b> Use <tt>__attribute__((type_tag_for_datatype(kind, type)))</tt> +on a declaration with that identifier: + +<blockquote> +<pre> +extern struct mpi_datatype mpi_datatype_int + __attribute__(( type_tag_for_datatype(mpi,int) )); +#define MPI_INT ((MPI_Datatype) &mpi_datatype_int) +</pre> +</blockquote></li> + +<li><b>Type tag that is an integral literal.</b> Introduce a <tt>static +const</tt> variable with a corresponding initializer value and attach +<tt>__attribute__((type_tag_for_datatype(kind, type)))</tt> on that +declaration, for example: + +<blockquote> +<pre> +#define MPI_INT ((MPI_Datatype) 42) +static const MPI_Datatype mpi_datatype_int + __attribute__(( type_tag_for_datatype(mpi,int) )) = 42 +</pre> +</blockquote></li> +</ul> + +<p>The attribute also accepts an optional third argument that determines how +the expression is compared to the type tag. There are two supported flags:</p> + +<ul><li><tt>layout_compatible</tt> will cause types to be compared according to +layout-compatibility rules (C++11 [class.mem] p 17, 18). This is +implemented to support annotating types like <tt>MPI_DOUBLE_INT</tt>. + +<p>For example:</p> +<blockquote> +<pre> +/* In mpi.h */ +struct internal_mpi_double_int { double d; int i; }; +extern struct mpi_datatype mpi_datatype_double_int + __attribute__(( type_tag_for_datatype(mpi, struct internal_mpi_double_int, + layout_compatible) )); + +#define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int) + +/* In user code */ +struct my_pair { double a; int b; }; +struct my_pair *buffer; +MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ... */); // no warning + +struct my_int_pair { int a; int b; } +struct my_int_pair *buffer2; +MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ... */); // warning: actual buffer element + // type 'struct my_int_pair' + // doesn't match specified MPI_Datatype +</pre> +</blockquote> +</li> + +<li><tt>must_be_null</tt> specifies that the expression should be a null +pointer constant, for example: + +<blockquote> +<pre> +/* In mpi.h */ +extern struct mpi_datatype mpi_datatype_null + __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) )); + +#define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null) + +/* In user code */ +MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ... */); // warning: MPI_DATATYPE_NULL + // was specified but buffer + // is not a null pointer +</pre> +</blockquote> +</li> +</ul> + </div> </body> </html> Modified: vendor/clang/dist/docs/ReleaseNotes.html ============================================================================== --- vendor/clang/dist/docs/ReleaseNotes.html Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/docs/ReleaseNotes.html Sun Aug 19 10:33:04 2012 (r239392) @@ -186,6 +186,25 @@ supported by the target, or if the compi model can be used. </p> +<h4>Type safety attributes</h4> +<p>Clang now supports type safety attributes that allow checking during compile +time that 'void *' function arguments and arguments for variadic functions are +of a particular type which is determined by some other argument to the same +function call.</p> + +<p>Usecases include:</p> +<ul> +<li>MPI library implementations, where these attributes enable checking that + buffer type matches the passed <code>MPI_Datatype</code>;</li> +<li> HDF5 library -- similar usecase as for MPI;</li> +<li> checking types of variadic functions' arguments for functions like +<code>fcntl()</code> and <code>ioctl()</code>.</li> +</ul> + +<p>See entries for <code>argument_with_type_tag</code>, +<code>pointer_with_type_tag</code> and <code>type_tag_for_datatype</code> +attributes in Clang language extensions documentation.</p> + <!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = --> <h3 id="newflags">New Compiler Flags</h3> <!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = --> Added: vendor/clang/dist/docs/analyzer/IPA.txt ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/clang/dist/docs/analyzer/IPA.txt Sun Aug 19 10:33:04 2012 (r239392) @@ -0,0 +1,96 @@ +Inlining +======== + +Inlining Modes +----------------------- +-analyzer-ipa=none - All inlining is disabled. +-analyzer-ipa=inlining - Turns on inlining when we can confidently find the function/method body corresponding to the call. (C functions, static functions, devirtualized C++ methods, ObjC class methods, ObjC instance methods when we are confident about the dynamic type of the instance). +-analyzer-ipa=dynamic - Inline instance methods for which the type is determined at runtime and we are not 100% sure that our type info is correct. For virtual calls, inline the most plausible definition. +-analyzer-ipa=dynamic-bifurcate - Same as -analyzer-ipa=dynamic, but the path is split. We inline on one branch and do not inline on the other. This mode does not drop the coverage in cases when the parent class has code that is only exercised when some of its methods are overriden. + +Currently, -analyzer-ipa=inlining is the default mode. + +Basics of Implementation +----------------------- + +The low-level mechanism of inlining a function is handled in ExprEngine::inlineCall and ExprEngine::processCallExit. If the conditions are right for inlining, a CallEnter node is created and added to the analysis work list. The CallEnter node marks the change to a new LocationContext representing the called function, and its state includes the contents of the new stack frame. When the CallEnter node is actually processed, its single successor will be a edge to the first CFG block in the function. + +Exiting an inlined function is a bit more work, fortunately broken up into reasonable steps: +1. The CoreEngine realizes we're at the end of an inlined call and generates a CallExitBegin node. +2. ExprEngine takes over (in processCallExit) and finds the return value of the function, if it has one. This is bound to the expression that triggered the call. (In the case of calls without origin expressions, such as destructors, this step is skipped.) +3. Dead symbols and bindings are cleaned out from the state, including any local bindings. +4. A CallExitEnd node is generated, which marks the transition back to the caller's LocationContext. +5. Custom post-call checks are processed and the final nodes are pushed back onto the work list, so that evaluation of the caller can continue. + +Retry Without Inlining +----------------------- + +In some cases, we would like to retry analyzes without inlining the particular call. Currently, we use this technique to recover the coverage in case we stop analyzing a path due to exceeding the maximum block count inside an inlined function. When this situation is detected, we walk up the path to find the first node before inlining was started and enqueue it on the WorkList with a special ReplayWithoutInlining bit added to it (ExprEngine::replayWithoutInlining). + +Deciding when to inline +----------------------- +In general, we try to inline as much as possible, since it provides a better summary of what actually happens in the program. However, there are some cases where we choose not to inline: +- if there is no definition available (of course) +- if we can't create a CFG or compute variable liveness for the function +- if we reach a cutoff of maximum stack depth (to avoid infinite recursion) +- if the function is variadic +- in C++, we don't inline constructors unless we know the destructor will be inlined as well +- in C++, we don't inline allocators (custom operator new implementations), since we don't properly handle deallocators (at the time of this writing) +- "Dynamic" calls are handled specially; see below. +- Engine:FunctionSummaries map stores additional information about declarations, some of which is collected at runtime based on previous analyzes of the function. We do not inline functions which were not profitable to inline in a different context (for example, if the maximum block count was exceeded, see Retry Without Inlining). + + +Dynamic calls and devirtualization +---------------------------------- +"Dynamic" calls are those that are resolved at runtime, such as C++ virtual method calls and Objective-C message sends. Due to the path-sensitive nature of the analyzer, we may be able to figure out the dynamic type of the object whose method is being called and thus "devirtualize" the call, i.e. find the actual method that will be called at runtime. (Obviously this is not always possible.) This is handled by CallEvent's getRuntimeDefinition method. + +Type information is tracked as DynamicTypeInfo, stored within the program state. If no DynamicTypeInfo has been explicitly set for a region, it will be inferred from the region's type or associated symbol. Information from symbolic regions is weaker than from true typed regions; a C++ object declared "A obj" is known to have the class 'A', but a reference "A &ref" may dynamically be a subclass of 'A'. The DynamicTypePropagation checker gathers and propagates the type information. + +(Warning: not all of the existing analyzer code has been retrofitted to use DynamicTypeInfo, nor is it universally appropriate. In particular, DynamicTypeInfo always applies to a region with all casts stripped off, but sometimes the information provided by casts can be useful.) + +When asked to provide a definition, the CallEvents for dynamic calls will use the type info in their state to provide the best definition of the method to be called. In some cases this devirtualization can be perfect or near-perfect, and we can inline the definition as usual. In others we can make a guess, but report that our guess may not be the method actually called at runtime. + +The -analyzer-ipa option has four different modes: none, inlining, dynamic, and dynamic-bifurcate. Under -analyzer-ipa=dynamic, all dynamic calls are inlined, whether we are certain or not that this will actually be the definition used at runtime. Under -analyzer-ipa=inlining, only "near-perfect" devirtualized calls are inlined*, and other dynamic calls are evaluated conservatively (as if no definition were available). + +* Currently, no Objective-C messages are not inlined under -analyzer-ipa=inlining, even if we are reasonably confident of the type of the receiver. We plan to enable this once we have tested our heuristics more thoroughly. + +The last option, -analyzer-ipa=dynamic-bifurcate, behaves similarly to "dynamic", but performs a conservative invalidation in the general virtual case in /addition/ to inlining. The details of this are discussed below. + + +Bifurcation +----------- +ExprEngine::BifurcateCall implements the -analyzer-ipa=dynamic-bifurcate mode. When a call is made on a region with dynamic type information, we bifurcate the path and add the region's processing mode to the GDM. Currently, there are 2 modes: DynamicDispatchModeInlined and DynamicDispatchModeConservative. Going forward, we consult the state of the region to make decisions on whether the calls should be inlined or not, which ensures that we have at most one split per region. The modes model the cases when the dynamic type information is perfectly correct and when the info is not correct (i.e. where the region is a subclass of the type we store in DynamicTypeInfo). + +Bifurcation mode allows for increased coverage in cases where the parent method contains code which is only executed when the class is subclassed. The disadvantages of this mode are a (considerable?) performance hit and the possibility of false positives on the path where the conservative mode is used. + + +Objective-C Message Heuristics +------------------------------ +We rely on a set of heuristics to partition the set of ObjC method calls into ones that require bifurcation and ones that do not (can or cannot be a subclass). Below are the cases when we consider that the dynamic type of the object is precise (cannot be a subclass): + - If the object was created with +alloc or +new and initialized with an -init method. + - If the calls are property accesses using dot syntax. This is based on the assumption that children rarely override properties, or do so in an essentially compatible way. + - If the class interface is declared inside the main source file. In this case it is unlikely that it will be subclassed. + - If the method is not declared outside of main source file, either by the receiver's class or by any superclasses. + + +C++ Inlining Caveats +-------------------- +C++11 [class.cdtor]p4 describes how the vtable of an object is modified as it is being constructed or destructed; that is, the type of the object depends on which base constructors have been completed. This is tracked using dynamic type info in the DynamicTypePropagation checker. + +Temporaries are poorly modelled right now because we're not confident in the placement + +'new' is poorly modelled due to some nasty CFG/design issues (elaborated in PR12014). 'delete' is essentially not modelled at all. + +Arrays of objects are modeled very poorly right now. We run only the first constructor and first destructor. Because of this, we don't inline any constructors or destructors for arrays. + + +CallEvent +========= + +A CallEvent represents a specific call to a function, method, or other body of code. It is path-sensitive, containing both the current state (ProgramStateRef) and stack space (LocationContext), and provides uniform access to the argument values and return type of a call, no matter how the call is written in the source or what sort of code body is being invoked. + +(For those familiar with Cocoa, CallEvent is roughly equivalent to NSInvocation.) + +CallEvent should be used whenever there is logic dealing with function calls that does not care how the call occurred. Examples include checking that arguments satisfy preconditions (such as __attribute__((nonnull))), and attempting to inline a call. + +CallEvents are reference-counted objects managed by a CallEventManager. While there is no inherent issue with persisting them (say, in the state's GDM), they are intended for short-lived use, and can be recreated from CFGElements or StackFrameContexts fairly easily. Modified: vendor/clang/dist/include/clang/AST/ASTContext.h ============================================================================== --- vendor/clang/dist/include/clang/AST/ASTContext.h Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/AST/ASTContext.h Sun Aug 19 10:33:04 2012 (r239392) @@ -474,8 +474,17 @@ public: Data.setPointer(RC); } + const Decl *getOriginalDecl() const LLVM_READONLY { + return OriginalDecl; + } + + void setOriginalDecl(const Decl *Orig) { + OriginalDecl = Orig; + } + private: llvm::PointerIntPair<const RawComment *, 2, Kind> Data; + const Decl *OriginalDecl; }; /// \brief Mapping from declarations to comments attached to any @@ -485,6 +494,10 @@ public: /// lazily. mutable llvm::DenseMap<const Decl *, RawCommentAndCacheFlags> RedeclComments; + /// \brief Mapping from declarations to parsed comments attached to any + /// redeclaration. + mutable llvm::DenseMap<const Decl *, comments::FullComment *> ParsedComments; + /// \brief Return the documentation comment attached to a given declaration, /// without looking into cache. RawComment *getRawCommentForDeclNoCache(const Decl *D) const; @@ -500,7 +513,12 @@ public: /// \brief Return the documentation comment attached to a given declaration. /// Returns NULL if no comment is attached. - const RawComment *getRawCommentForAnyRedecl(const Decl *D) const; + /// + /// \param OriginalDecl if not NULL, is set to declaration AST node that had + /// the comment, if the comment we found comes from a redeclaration. + const RawComment *getRawCommentForAnyRedecl( + const Decl *D, + const Decl **OriginalDecl = NULL) const; /// Return parsed documentation comment attached to a given declaration. /// Returns NULL if no comment is attached. Modified: vendor/clang/dist/include/clang/AST/Attr.h ============================================================================== --- vendor/clang/dist/include/clang/AST/Attr.h Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/AST/Attr.h Sun Aug 19 10:33:04 2012 (r239392) @@ -105,7 +105,8 @@ public: virtual bool isLateParsed() const { return false; } // Pretty print this attribute. - virtual void printPretty(llvm::raw_ostream &OS, ASTContext &C) const = 0; + virtual void printPretty(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const = 0; // Implement isa/cast/dyncast/etc. static bool classof(const Attr *) { return true; } Modified: vendor/clang/dist/include/clang/AST/CommentCommandTraits.h ============================================================================== --- vendor/clang/dist/include/clang/AST/CommentCommandTraits.h Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/AST/CommentCommandTraits.h Sun Aug 19 10:33:04 2012 (r239392) @@ -35,14 +35,14 @@ public: /// A verbatim-like block command eats every character (except line starting /// decorations) until matching end command is seen or comment end is hit. /// - /// \param BeginName name of the command that starts the verbatim block. + /// \param StartName name of the command that starts the verbatim block. /// \param [out] EndName name of the command that ends the verbatim block. /// /// \returns true if a given command is a verbatim block command. bool isVerbatimBlockCommand(StringRef StartName, StringRef &EndName) const; /// \brief Register a new verbatim block command. - void addVerbatimBlockCommand(StringRef BeginName, StringRef EndName); + void addVerbatimBlockCommand(StringRef StartName, StringRef EndName); /// \brief Check if a given command is a verbatim line command. /// @@ -90,7 +90,7 @@ public: private: struct VerbatimBlockCommand { - StringRef BeginName; + StringRef StartName; StringRef EndName; }; Modified: vendor/clang/dist/include/clang/AST/DeclBase.h ============================================================================== --- vendor/clang/dist/include/clang/AST/DeclBase.h Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/AST/DeclBase.h Sun Aug 19 10:33:04 2012 (r239392) @@ -858,10 +858,10 @@ public: raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation = 0); // Debuggers don't usually respect default arguments. - LLVM_ATTRIBUTE_USED void dump() const { dump(llvm::errs()); } + LLVM_ATTRIBUTE_USED void dump() const; void dump(raw_ostream &Out) const; // Debuggers don't usually respect default arguments. - LLVM_ATTRIBUTE_USED void dumpXML() const { dumpXML(llvm::errs()); } + LLVM_ATTRIBUTE_USED void dumpXML() const; void dumpXML(raw_ostream &OS) const; private: Modified: vendor/clang/dist/include/clang/AST/DeclCXX.h ============================================================================== --- vendor/clang/dist/include/clang/AST/DeclCXX.h Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/AST/DeclCXX.h Sun Aug 19 10:33:04 2012 (r239392) @@ -1646,14 +1646,17 @@ public: /// \brief Find the method in RD that corresponds to this one. /// /// Find if RD or one of the classes it inherits from override this method. - /// If so, return it. RD is assumed to be a base class of the class defining - /// this method (or be the class itself). + /// If so, return it. RD is assumed to be a subclass of the class defining + /// this method (or be the class itself), unless MayBeBase is set to true. CXXMethodDecl * - getCorrespondingMethodInClass(const CXXRecordDecl *RD); + getCorrespondingMethodInClass(const CXXRecordDecl *RD, + bool MayBeBase = false); const CXXMethodDecl * - getCorrespondingMethodInClass(const CXXRecordDecl *RD) const { - return const_cast<CXXMethodDecl*>(this)->getCorrespondingMethodInClass(RD); + getCorrespondingMethodInClass(const CXXRecordDecl *RD, + bool MayBeBase = false) const { + return const_cast<CXXMethodDecl *>(this) + ->getCorrespondingMethodInClass(RD, MayBeBase); } // Implement isa/cast/dyncast/etc. Modified: vendor/clang/dist/include/clang/AST/DeclGroup.h ============================================================================== --- vendor/clang/dist/include/clang/AST/DeclGroup.h Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/AST/DeclGroup.h Sun Aug 19 10:33:04 2012 (r239392) @@ -26,7 +26,11 @@ class DeclGroupIterator; class DeclGroup { // FIXME: Include a TypeSpecifier object. - unsigned NumDecls; + union { + unsigned NumDecls; + + Decl *Aligner; + }; private: DeclGroup() : NumDecls(0) {} Modified: vendor/clang/dist/include/clang/AST/DeclLookups.h ============================================================================== --- vendor/clang/dist/include/clang/AST/DeclLookups.h Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/AST/DeclLookups.h Sun Aug 19 10:33:04 2012 (r239392) @@ -67,7 +67,7 @@ public: DeclContext::all_lookups_iterator DeclContext::lookups_begin() const { DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext(); - if (hasExternalVisibleStorage()) + if (Primary->hasExternalVisibleStorage()) getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary); if (StoredDeclsMap *Map = Primary->buildLookup()) return all_lookups_iterator(Map->begin(), Map->end()); @@ -76,7 +76,7 @@ DeclContext::all_lookups_iterator DeclCo DeclContext::all_lookups_iterator DeclContext::lookups_end() const { DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext(); - if (hasExternalVisibleStorage()) + if (Primary->hasExternalVisibleStorage()) getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary); if (StoredDeclsMap *Map = Primary->buildLookup()) return all_lookups_iterator(Map->end(), Map->end()); Modified: vendor/clang/dist/include/clang/AST/PrettyPrinter.h ============================================================================== --- vendor/clang/dist/include/clang/AST/PrettyPrinter.h Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/AST/PrettyPrinter.h Sun Aug 19 10:33:04 2012 (r239392) @@ -34,19 +34,19 @@ public: struct PrintingPolicy { /// \brief Create a default printing policy for C. PrintingPolicy(const LangOptions &LO) - : Indentation(2), LangOpts(LO), SuppressSpecifiers(false), + : LangOpts(LO), Indentation(2), SuppressSpecifiers(false), SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false), SuppressUnwrittenScope(false), SuppressInitializers(false), - Dump(false), ConstantArraySizeAsWritten(false), - AnonymousTagLocations(true), SuppressStrongLifetime(false), - Bool(LO.Bool) { } - - /// \brief The number of spaces to use to indent each line. - unsigned Indentation : 8; + ConstantArraySizeAsWritten(false), AnonymousTagLocations(true), + SuppressStrongLifetime(false), Bool(LO.Bool), + DumpSourceManager(0) { } /// \brief What language we're printing. LangOptions LangOpts; + /// \brief The number of spaces to use to indent each line. + unsigned Indentation : 8; + /// \brief Whether we should suppress printing of the actual specifiers for /// the given type or declaration. /// @@ -103,12 +103,6 @@ struct PrintingPolicy { /// internal initializer constructed for x will not be printed. bool SuppressInitializers : 1; - /// \brief True when we are "dumping" rather than "pretty-printing", - /// where dumping involves printing the internal details of the AST - /// and pretty-printing involves printing something similar to - /// source code. - bool Dump : 1; - /// \brief Whether we should print the sizes of constant array expressions /// as written in the sources. /// @@ -139,6 +133,12 @@ struct PrintingPolicy { /// \brief Whether we can use 'bool' rather than '_Bool', even if the language /// doesn't actually have 'bool' (because, e.g., it is defined as a macro). unsigned Bool : 1; + + /// \brief If we are "dumping" rather than "pretty-printing", this points to + /// a SourceManager which will be used to dump SourceLocations. Dumping + /// involves printing the internal details of the AST and pretty-printing + /// involves printing something similar to source code. + SourceManager *DumpSourceManager; }; } // end namespace clang Modified: vendor/clang/dist/include/clang/AST/RawCommentList.h ============================================================================== --- vendor/clang/dist/include/clang/AST/RawCommentList.h Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/AST/RawCommentList.h Sun Aug 19 10:33:04 2012 (r239392) @@ -55,16 +55,11 @@ public: /// Is this comment attached to any declaration? bool isAttached() const LLVM_READONLY { - return !DeclOrParsedComment.isNull(); + return IsAttached; } - /// Return the declaration that this comment is attached to. - const Decl *getDecl() const; - - /// Set the declaration that this comment is attached to. - void setDecl(const Decl *D) { - assert(DeclOrParsedComment.isNull()); - DeclOrParsedComment = D; + void setAttached() { + IsAttached = true; } /// Returns true if it is a comment that should be put after a member: @@ -118,28 +113,23 @@ public: return extractBriefText(Context); } - /// Returns a \c FullComment AST node, parsing the comment if needed. - comments::FullComment *getParsed(const ASTContext &Context) const { - if (comments::FullComment *FC = - DeclOrParsedComment.dyn_cast<comments::FullComment *>()) - return FC; - - return parse(Context); - } + /// Parse the comment, assuming it is attached to decl \c D. + comments::FullComment *parse(const ASTContext &Context, const Decl *D) const; private: SourceRange Range; mutable StringRef RawText; mutable const char *BriefText; - mutable llvm::PointerUnion<const Decl *, comments::FullComment *> - DeclOrParsedComment; mutable bool RawTextValid : 1; ///< True if RawText is valid mutable bool BriefTextValid : 1; ///< True if BriefText is valid unsigned Kind : 3; + /// True if comment is attached to a declaration in ASTContext. + bool IsAttached : 1; + bool IsTrailingComment : 1; bool IsAlmostTrailingComment : 1; @@ -152,7 +142,7 @@ private: RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment, bool IsAlmostTrailingComment) : Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K), - IsTrailingComment(IsTrailingComment), + IsAttached(false), IsTrailingComment(IsTrailingComment), IsAlmostTrailingComment(IsAlmostTrailingComment), BeginLineValid(false), EndLineValid(false) { } @@ -161,8 +151,6 @@ private: const char *extractBriefText(const ASTContext &Context) const; - comments::FullComment *parse(const ASTContext &Context) const; - friend class ASTReader; }; Modified: vendor/clang/dist/include/clang/AST/Stmt.h ============================================================================== --- vendor/clang/dist/include/clang/AST/Stmt.h Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/AST/Stmt.h Sun Aug 19 10:33:04 2012 (r239392) @@ -373,15 +373,9 @@ public: /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST /// back to its original source language syntax. - void dumpPretty(ASTContext& Context) const; + void dumpPretty(ASTContext &Context) const; void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, - unsigned Indentation = 0) const { - printPretty(OS, *(ASTContext*)0, Helper, Policy, Indentation); - } - void printPretty(raw_ostream &OS, ASTContext &Context, - PrinterHelper *Helper, - const PrintingPolicy &Policy, unsigned Indentation = 0) const; /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only @@ -1620,36 +1614,40 @@ public: /// MSAsmStmt - This represents a MS inline-assembly statement extension. /// class MSAsmStmt : public Stmt { - SourceLocation AsmLoc, EndLoc; + SourceLocation AsmLoc, LBraceLoc, EndLoc; std::string AsmStr; bool IsSimple; bool IsVolatile; unsigned NumAsmToks; - unsigned NumLineEnds; + unsigned NumInputs; + unsigned NumOutputs; unsigned NumClobbers; Token *AsmToks; - unsigned *LineEnds; + IdentifierInfo **Names; Stmt **Exprs; StringRef *Clobbers; public: - MSAsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, - bool isvolatile, ArrayRef<Token> asmtoks, - ArrayRef<unsigned> lineends, StringRef asmstr, - ArrayRef<StringRef> clobbers, SourceLocation endloc); + MSAsmStmt(ASTContext &C, SourceLocation asmloc, SourceLocation lbraceloc, + bool issimple, bool isvolatile, ArrayRef<Token> asmtoks, + ArrayRef<IdentifierInfo*> inputs, ArrayRef<IdentifierInfo*> outputs, + StringRef asmstr, ArrayRef<StringRef> clobbers, + SourceLocation endloc); SourceLocation getAsmLoc() const { return AsmLoc; } void setAsmLoc(SourceLocation L) { AsmLoc = L; } + SourceLocation getLBraceLoc() const { return LBraceLoc; } + void setLBraceLoc(SourceLocation L) { LBraceLoc = L; } SourceLocation getEndLoc() const { return EndLoc; } void setEndLoc(SourceLocation L) { EndLoc = L; } + bool hasBraces() const { return LBraceLoc.isValid(); } + unsigned getNumAsmToks() { return NumAsmToks; } Token *getAsmToks() { return AsmToks; } - unsigned getNumLineEnds() { return NumLineEnds; } - unsigned *getLineEnds() { return LineEnds; } bool isVolatile() const { return IsVolatile; } void setVolatile(bool V) { IsVolatile = V; } @@ -1665,7 +1663,7 @@ public: //===--- Other ---===// unsigned getNumClobbers() const { return NumClobbers; } - StringRef getClobber(unsigned i) { return Clobbers[i]; } + StringRef getClobber(unsigned i) const { return Clobbers[i]; } SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AsmLoc, EndLoc); Modified: vendor/clang/dist/include/clang/AST/TemplateBase.h ============================================================================== --- vendor/clang/dist/include/clang/AST/TemplateBase.h Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/AST/TemplateBase.h Sun Aug 19 10:33:04 2012 (r239392) @@ -510,17 +510,23 @@ public: /// This is safe to be used inside an AST node, in contrast with /// TemplateArgumentListInfo. struct ASTTemplateArgumentListInfo { - /// \brief The source location of the left angle bracket ('<'); + /// \brief The source location of the left angle bracket ('<'). SourceLocation LAngleLoc; - /// \brief The source location of the right angle bracket ('>'); + /// \brief The source location of the right angle bracket ('>'). SourceLocation RAngleLoc; - /// \brief The number of template arguments in TemplateArgs. - /// The actual template arguments (if any) are stored after the - /// ExplicitTemplateArgumentList structure. - unsigned NumTemplateArgs; - + union { + /// \brief The number of template arguments in TemplateArgs. + /// The actual template arguments (if any) are stored after the + /// ExplicitTemplateArgumentList structure. + unsigned NumTemplateArgs; + + /// Force ASTTemplateArgumentListInfo to the right alignment + /// for the following array of TemplateArgumentLocs. + void *Aligner; + }; + /// \brief Retrieve the template arguments TemplateArgumentLoc *getTemplateArgs() { return reinterpret_cast<TemplateArgumentLoc *> (this + 1); Modified: vendor/clang/dist/include/clang/AST/TypeLoc.h ============================================================================== --- vendor/clang/dist/include/clang/AST/TypeLoc.h Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/AST/TypeLoc.h Sun Aug 19 10:33:04 2012 (r239392) @@ -1061,7 +1061,6 @@ public: struct FunctionLocInfo { SourceLocation LocalRangeBegin; SourceLocation LocalRangeEnd; - bool TrailingReturn; }; /// \brief Wrapper for source info for functions. @@ -1084,13 +1083,6 @@ public: getLocalData()->LocalRangeEnd = L; } - bool getTrailingReturn() const { - return getLocalData()->TrailingReturn; - } - void setTrailingReturn(bool Trailing) { - getLocalData()->TrailingReturn = Trailing; - } - ArrayRef<ParmVarDecl *> getParams() const { return ArrayRef<ParmVarDecl *>(getParmArray(), getNumArgs()); } @@ -1119,7 +1111,6 @@ public: void initializeLocal(ASTContext &Context, SourceLocation Loc) { setLocalRangeBegin(Loc); setLocalRangeEnd(Loc); - setTrailingReturn(false); for (unsigned i = 0, e = getNumArgs(); i != e; ++i) setArg(i, NULL); } Modified: vendor/clang/dist/include/clang/ASTMatchers/ASTMatchers.h ============================================================================== --- vendor/clang/dist/include/clang/ASTMatchers/ASTMatchers.h Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/ASTMatchers/ASTMatchers.h Sun Aug 19 10:33:04 2012 (r239392) @@ -50,6 +50,7 @@ #include "clang/ASTMatchers/ASTMatchersMacros.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Regex.h" +#include <iterator> namespace clang { namespace ast_matchers { @@ -195,6 +196,75 @@ AST_MATCHER_P(ClassTemplateSpecializatio return false; } +/// \brief Matches expressions that match InnerMatcher after any implicit casts +/// are stripped off. +/// +/// Parentheses and explicit casts are not discarded. +/// Given +/// int arr[5]; +/// int a = 0; +/// char b = 0; +/// const int c = a; +/// int *d = arr; +/// long e = (long) 0l; +/// The matchers +/// variable(hasInitializer(ignoringImpCasts(integerLiteral()))) +/// variable(hasInitializer(ignoringImpCasts(declarationReference()))) +/// would match the declarations for a, b, c, and d, but not e. +/// while +/// variable(hasInitializer(integerLiteral())) +/// variable(hasInitializer(declarationReference())) +/// only match the declarations for b, c, and d. +AST_MATCHER_P(Expr, ignoringImpCasts, + internal::Matcher<Expr>, InnerMatcher) { + return InnerMatcher.matches(*Node.IgnoreImpCasts(), Finder, Builder); +} + +/// \brief Matches expressions that match InnerMatcher after parentheses and +/// casts are stripped off. +/// +/// Implicit and non-C Style casts are also discarded. +/// Given +/// int a = 0; +/// char b = (0); +/// void* c = reinterpret_cast<char*>(0); +/// char d = char(0); +/// The matcher +/// variable(hasInitializer(ignoringParenCasts(integerLiteral()))) +/// would match the declarations for a, b, c, and d. +/// while +/// variable(hasInitializer(integerLiteral())) +/// only match the declaration for a. +AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher<Expr>, InnerMatcher) { + return InnerMatcher.matches(*Node.IgnoreParenCasts(), Finder, Builder); +} + +/// \brief Matches expressions that match InnerMatcher after implicit casts and +/// parentheses are stripped off. +/// +/// Explicit casts are not discarded. +/// Given +/// int arr[5]; +/// int a = 0; +/// char b = (0); +/// const int c = a; +/// int *d = (arr); +/// long e = ((long) 0l); +/// The matchers +/// variable(hasInitializer(ignoringParenImpCasts( +/// integerLiteral()))) +/// variable(hasInitializer(ignoringParenImpCasts( +/// declarationReference()))) +/// would match the declarations for a, b, c, and d, but not e. +/// while +/// variable(hasInitializer(integerLiteral())) +/// variable(hasInitializer(declarationReference())) +/// would only match the declaration for a. +AST_MATCHER_P(Expr, ignoringParenImpCasts, + internal::Matcher<Expr>, InnerMatcher) { + return InnerMatcher.matches(*Node.IgnoreParenImpCasts(), Finder, Builder); +} + /// \brief Matches classTemplateSpecializations where the n'th TemplateArgument /// matches the given Matcher. /// @@ -691,6 +761,19 @@ const internal::VariadicDynCastAllOfMatc Expr, ImplicitCastExpr> implicitCast; +/// \brief Matches any cast nodes of Clang's AST. +/// +/// Example: castExpr() matches each of the following: +/// (int) 3; +/// const_cast<Expr *>(SubExpr); +/// char c = 0; +/// but does not match +/// int i = (0); +/// int k = 0; +const internal::VariadicDynCastAllOfMatcher< + Expr, + CastExpr> castExpr; + /// \brief Matches functional cast expressions /// /// Example: Matches Foo(bar); @@ -1193,6 +1276,21 @@ AST_MATCHER_P(DeclRefExpr, throughUsingD return false; } +/// \brief Matches the Decl of a DeclStmt which has a single declaration. +/// +/// Given +/// int a, b; +/// int c; +/// declarationStatement(hasSingleDecl(anything())) +/// matches 'int c;' but not 'int a, b;'. +AST_MATCHER_P(DeclStmt, hasSingleDecl, internal::Matcher<Decl>, InnerMatcher) { + if (Node.isSingleDecl()) { + const Decl *FoundDecl = Node.getSingleDecl(); + return InnerMatcher.matches(*FoundDecl, Finder, Builder); + } + return false; +} + /// \brief Matches a variable declaration that has an initializer expression /// that matches the given matcher. /// @@ -1238,6 +1336,44 @@ AST_POLYMORPHIC_MATCHER_P2( *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder)); } +/// \brief Matches declaration statements that contain a specific number of +/// declarations. +/// +/// Example: Given +/// int a, b; +/// int c; +/// int d = 2, e; +/// declCountIs(2) +/// matches 'int a, b;' and 'int d = 2, e;', but not 'int c;'. +AST_MATCHER_P(DeclStmt, declCountIs, unsigned, N) { + return std::distance(Node.decl_begin(), Node.decl_end()) == N; +} + +/// \brief Matches the n'th declaration of a declaration statement. +/// +/// Note that this does not work for global declarations because the AST +/// breaks up multiple-declaration DeclStmt's into multiple single-declaration +/// DeclStmt's. +/// Example: Given non-global declarations +/// int a, b = 0; +/// int c; +/// int d = 2, e; +/// declarationStatement(containsDeclaration( +/// 0, variable(hasInitializer(anything())))) +/// matches only 'int d = 2, e;', and +/// declarationStatement(containsDeclaration(1, variable())) +/// matches 'int a, b = 0' as well as 'int d = 2, e;' +/// but 'int c;' is not matched. +AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N, + internal::Matcher<Decl>, InnerMatcher) { + const unsigned NumDecls = std::distance(Node.decl_begin(), Node.decl_end()); + if (N >= NumDecls) + return false; + DeclStmt::const_decl_iterator Iterator = Node.decl_begin(); + std::advance(Iterator, N); + return InnerMatcher.matches(**Iterator, Finder, Builder); +} + /// \brief Matches a constructor initializer. /// /// Given @@ -1385,6 +1521,18 @@ AST_MATCHER_P(FunctionDecl, returns, int return Matcher.matches(Node.getResultType(), Finder, Builder); } +/// \brief Matches extern "C" function declarations. +/// +/// Given: +/// extern "C" void f() {} +/// extern "C" { void g() {} } +/// void h() {} +/// function(isExternC()) +/// matches the declaration of f and g, but not the declaration h +AST_MATCHER(FunctionDecl, isExternC) { + return Node.isExternC(); +} + /// \brief Matches the condition expression of an if statement, for loop, /// or conditional operator. /// Modified: vendor/clang/dist/include/clang/Basic/Attr.td ============================================================================== --- vendor/clang/dist/include/clang/Basic/Attr.td Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/Basic/Attr.td Sun Aug 19 10:33:04 2012 (r239392) @@ -826,6 +826,27 @@ def SharedLocksRequired : InheritableAtt let TemplateDependent = 1; } +// Type safety attributes for `void *' pointers and type tags. + +def ArgumentWithTypeTag : InheritableAttr { + let Spellings = [GNU<"argument_with_type_tag">, + GNU<"pointer_with_type_tag">]; + let Args = [IdentifierArgument<"ArgumentKind">, + UnsignedArgument<"ArgumentIdx">, + UnsignedArgument<"TypeTagIdx">, + BoolArgument<"IsPointer">]; + let Subjects = [Function]; +} + +def TypeTagForDatatype : InheritableAttr { + let Spellings = [GNU<"type_tag_for_datatype">]; + let Args = [IdentifierArgument<"ArgumentKind">, + TypeArgument<"MatchingCType">, + BoolArgument<"LayoutCompatible">, + BoolArgument<"MustBeNull">]; + let Subjects = [Var]; +} + // Microsoft-related attributes def MsStruct : InheritableAttr { Modified: vendor/clang/dist/include/clang/Basic/Builtins.def ============================================================================== --- vendor/clang/dist/include/clang/Basic/Builtins.def Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/Basic/Builtins.def Sun Aug 19 10:33:04 2012 (r239392) @@ -376,9 +376,9 @@ BUILTIN(__builtin_ctz , "iUi" , "nc") BUILTIN(__builtin_ctzl , "iULi" , "nc") BUILTIN(__builtin_ctzll, "iULLi", "nc") // TODO: int ctzimax(uintmax_t) -BUILTIN(__builtin_ffs , "iUi" , "nc") -BUILTIN(__builtin_ffsl , "iULi" , "nc") -BUILTIN(__builtin_ffsll, "iULLi", "nc") +BUILTIN(__builtin_ffs , "ii" , "nc") +BUILTIN(__builtin_ffsl , "iLi" , "nc") +BUILTIN(__builtin_ffsll, "iLLi", "nc") BUILTIN(__builtin_parity , "iUi" , "nc") BUILTIN(__builtin_parityl , "iULi" , "nc") BUILTIN(__builtin_parityll, "iULLi", "nc") Modified: vendor/clang/dist/include/clang/Basic/DiagnosticGroups.td ============================================================================== --- vendor/clang/dist/include/clang/Basic/DiagnosticGroups.td Sun Aug 19 10:32:32 2012 (r239391) +++ vendor/clang/dist/include/clang/Basic/DiagnosticGroups.td Sun Aug 19 10:33:04 2012 (r239392) @@ -155,6 +155,8 @@ def MethodAccess : DiagGroup<"objc-metho def ObjCReceiver : DiagGroup<"receiver-expr">; def OverlengthStrings : DiagGroup<"overlength-strings">; def OverloadedVirtual : DiagGroup<"overloaded-virtual">; +def PrivateExtern : DiagGroup<"private-extern">; +def SelTypeCast : DiagGroup<"cast-of-sel-type">; def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">; def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">; def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">; @@ -341,6 +343,8 @@ def FormatNonLiteral : DiagGroup<"format def Format2 : DiagGroup<"format=2", [FormatNonLiteral, FormatSecurity, FormatY2K]>; +def TypeSafety : DiagGroup<"type-safety">; + def Extra : DiagGroup<"extra", [ MissingFieldInitializers, IgnoredQualifiers, @@ -371,7 +375,9 @@ def Most : DiagGroup<"most", [ Unused, VolatileRegisterVar, ObjCMissingSuperCalls, - OverloadedVirtual + OverloadedVirtual, *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201208191033.q7JAX5KX070368>