aboutsummaryrefslogtreecommitdiff
path: root/lib
AgeCommit message (Collapse)Author
2013-04-04[analyzer] Reduced the unwanted correlations between checkers living inside ↵Anton Yartsev
MallocChecker.cpp This fixes an issue pointed to by Jordan: if unix.Malloc and unix.MismatchedDeallocator are both on, then we end up still tracking leaks of memory allocated by new. Moved the guards right before emitting the bug reports to unify and simplify the logic of handling of multiple checkers. Now all the checkers perform their checks regardless of if they were enabled, or not, and it is decided just before the emitting of the report, if it should be emitted. (idea from Anna). Additional changes: improved test coverage for checker correlations; refactoring: BadDealloc -> MismatchedDealloc git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178814 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Revert 178811 until I fix the unit tests.Tanya Lattner
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178813 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Add an error to check that all program scope variables are in the constant ↵Tanya Lattner
address space in OpenCL. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178811 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04[analyzer] Enable destructor inlining by default (c++-inlining=destructors).Jordan Rose
This turns on not only destructor inlining, but inlining of constructors for types with non-trivial destructors. Per r178516, we will still not inline the constructor or destructor of anything that looks like a container unless the analyzer-config option 'c++-container-inlining' is set to 'true'. In addition to the more precise path-sensitive model, this allows us to catch simple smart pointer issues: #include <memory> void test() { std::auto_ptr<int> releaser(new int[4]); } // memory allocated with 'new[]' should not be deleted with 'delete' <rdar://problem/12295363> git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178805 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Add some documentation for PNaClABIInfo.Eli Bendersky
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178802 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04[analyzer] RetainCountChecker: refactor annotation handling.Jordan Rose
...and add a new test case. I thought this was broken, but it isn't; refactoring and reformatting anyway so that I don't make the same mistake again. No functionality change. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178799 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Initial support for struct-path aware TBAA.Manman Ren
Added TBAABaseType and TBAAOffset in LValue. These two fields are initialized to the actual type and 0, and are updated in EmitLValueForField. Path-aware TBAA tags are enabled for EmitLoadOfScalar and EmitStoreOfScalar. Added command line option -struct-path-tbaa. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178797 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04revert r178784 since it does not have a commit messageManman Ren
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178796 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Don't patch the storage class of static data members.Rafael Espindola
This removes a bit of patching that survived r178663. Without it we can produce better a better error message for const int a = 5; static const int a; git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178795 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Index: include/clang/Driver/CC1Options.tdManman Ren
=================================================================== --- include/clang/Driver/CC1Options.td (revision 178718) +++ include/clang/Driver/CC1Options.td (working copy) @@ -161,6 +161,8 @@ HelpText<"Use register sized accesses to bit-fields, when possible.">; def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">, HelpText<"Turn off Type Based Alias Analysis">; +def struct_path_tbaa : Flag<["-"], "struct-path-tbaa">, + HelpText<"Turn on struct-path aware Type Based Alias Analysis">; def masm_verbose : Flag<["-"], "masm-verbose">, HelpText<"Generate verbose assembly output">; def mcode_model : Separate<["-"], "mcode-model">, Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td (revision 178718) +++ include/clang/Driver/Options.td (working copy) @@ -587,6 +587,7 @@ Flags<[CC1Option]>, HelpText<"Disable spell-checking">; def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group<f_Group>; def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>; +def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group<f_Group>; def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group<f_Group>; def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group<f_Group>; def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group<f_Group>, Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def (revision 178718) +++ include/clang/Frontend/CodeGenOptions.def (working copy) @@ -85,6 +85,7 @@ VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. +CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA. CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero ///< offset in AddressSanitizer. Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp (revision 178718) +++ lib/CodeGen/CGExpr.cpp (working copy) @@ -1044,7 +1044,8 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue) { return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(), lvalue.getAlignment().getQuantity(), - lvalue.getType(), lvalue.getTBAAInfo()); + lvalue.getType(), lvalue.getTBAAInfo(), + lvalue.getTBAABaseType(), lvalue.getTBAAOffset()); } static bool hasBooleanRepresentation(QualType Ty) { @@ -1106,7 +1107,9 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo) { + llvm::MDNode *TBAAInfo, + QualType TBAABaseType, + uint64_t TBAAOffset) { // For better performance, handle vector loads differently. if (Ty->isVectorType()) { llvm::Value *V; @@ -1158,8 +1161,11 @@ Load->setVolatile(true); if (Alignment) Load->setAlignment(Alignment); - if (TBAAInfo) - CGM.DecorateInstruction(Load, TBAAInfo); + if (TBAAInfo) { + llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, + TBAAOffset); + CGM.DecorateInstruction(Load, TBAAPath); + } if ((SanOpts->Bool && hasBooleanRepresentation(Ty)) || (SanOpts->Enum && Ty->getAs<EnumType>())) { @@ -1217,7 +1223,8 @@ bool Volatile, unsigned Alignment, QualType Ty, llvm::MDNode *TBAAInfo, - bool isInit) { + bool isInit, QualType TBAABaseType, + uint64_t TBAAOffset) { // Handle vectors differently to get better performance. if (Ty->isVectorType()) { @@ -1268,15 +1275,19 @@ llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile); if (Alignment) Store->setAlignment(Alignment); - if (TBAAInfo) - CGM.DecorateInstruction(Store, TBAAInfo); + if (TBAAInfo) { + llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, + TBAAOffset); + CGM.DecorateInstruction(Store, TBAAPath); + } } void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue, bool isInit) { EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(), lvalue.getAlignment().getQuantity(), lvalue.getType(), - lvalue.getTBAAInfo(), isInit); + lvalue.getTBAAInfo(), isInit, lvalue.getTBAABaseType(), + lvalue.getTBAAOffset()); } /// EmitLoadOfLValue - Given an expression that represents a value lvalue, this @@ -2494,9 +2505,12 @@ llvm::Value *addr = base.getAddress(); unsigned cvr = base.getVRQualifiers(); + bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA; if (rec->isUnion()) { // For unions, there is no pointer adjustment. assert(!type->isReferenceType() && "union has reference member"); + // TODO: handle path-aware TBAA for union. + TBAAPath = false; } else { // For structs, we GEP to the field that the record layout suggests. unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field); @@ -2508,6 +2522,8 @@ if (cvr & Qualifiers::Volatile) load->setVolatile(true); load->setAlignment(alignment.getQuantity()); + // Loading the reference will disable path-aware TBAA. + TBAAPath = false; if (CGM.shouldUseTBAA()) { llvm::MDNode *tbaa; if (mayAlias) @@ -2541,6 +2557,16 @@ LValue LV = MakeAddrLValue(addr, type, alignment); LV.getQuals().addCVRQualifiers(cvr); + if (TBAAPath) { + const ASTRecordLayout &Layout = + getContext().getASTRecordLayout(field->getParent()); + // Set the base type to be the base type of the base LValue and + // update offset to be relative to the base type. + LV.setTBAABaseType(base.getTBAABaseType()); + LV.setTBAAOffset(base.getTBAAOffset() + + Layout.getFieldOffset(field->getFieldIndex()) / + getContext().getCharWidth()); + } // __weak attribute on a field is ignored. if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak) Index: lib/CodeGen/CGValue.h =================================================================== --- lib/CodeGen/CGValue.h (revision 178718) +++ lib/CodeGen/CGValue.h (working copy) @@ -157,6 +157,11 @@ Expr *BaseIvarExp; + /// Used by struct-path-aware TBAA. + QualType TBAABaseType; + /// Offset relative to the base type. + uint64_t TBAAOffset; + /// TBAAInfo - TBAA information to attach to dereferences of this LValue. llvm::MDNode *TBAAInfo; @@ -175,6 +180,10 @@ this->ImpreciseLifetime = false; this->ThreadLocalRef = false; this->BaseIvarExp = 0; + + // Initialize fields for TBAA. + this->TBAABaseType = Type; + this->TBAAOffset = 0; this->TBAAInfo = TBAAInfo; } @@ -232,6 +241,12 @@ Expr *getBaseIvarExp() const { return BaseIvarExp; } void setBaseIvarExp(Expr *V) { BaseIvarExp = V; } + QualType getTBAABaseType() const { return TBAABaseType; } + void setTBAABaseType(QualType T) { TBAABaseType = T; } + + uint64_t getTBAAOffset() const { return TBAAOffset; } + void setTBAAOffset(uint64_t O) { TBAAOffset = O; } + llvm::MDNode *getTBAAInfo() const { return TBAAInfo; } void setTBAAInfo(llvm::MDNode *N) { TBAAInfo = N; } Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h (revision 178718) +++ lib/CodeGen/CodeGenFunction.h (working copy) @@ -2211,7 +2211,9 @@ /// the LLVM value representation. llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo = 0); + llvm::MDNode *TBAAInfo = 0, + QualType TBAABaseTy = QualType(), + uint64_t TBAAOffset = 0); /// EmitLoadOfScalar - Load a scalar value from an address, taking /// care to appropriately convert from the memory representation to @@ -2224,7 +2226,9 @@ /// the LLVM value representation. void EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo = 0, bool isInit=false); + llvm::MDNode *TBAAInfo = 0, bool isInit = false, + QualType TBAABaseTy = QualType(), + uint64_t TBAAOffset = 0); /// EmitStoreOfScalar - Store a scalar value to an address, taking /// care to appropriately convert from the memory representation to Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp (revision 178718) +++ lib/CodeGen/CodeGenModule.cpp (working copy) @@ -227,6 +227,20 @@ return TBAA->getTBAAStructInfo(QTy); } +llvm::MDNode *CodeGenModule::getTBAAStructTypeInfo(QualType QTy) { + if (!TBAA) + return 0; + return TBAA->getTBAAStructTypeInfo(QTy); +} + +llvm::MDNode *CodeGenModule::getTBAAStructTagInfo(QualType BaseTy, + llvm::MDNode *AccessN, + uint64_t O) { + if (!TBAA) + return 0; + return TBAA->getTBAAStructTagInfo(BaseTy, AccessN, O); +} + void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst, llvm::MDNode *TBAAInfo) { Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo); Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h (revision 178718) +++ lib/CodeGen/CodeGenModule.h (working copy) @@ -501,6 +501,11 @@ llvm::MDNode *getTBAAInfo(QualType QTy); llvm::MDNode *getTBAAInfoForVTablePtr(); llvm::MDNode *getTBAAStructInfo(QualType QTy); + /// Return the MDNode in the type DAG for the given struct type. + llvm::MDNode *getTBAAStructTypeInfo(QualType QTy); + /// Return the path-aware tag for given base type, access node and offset. + llvm::MDNode *getTBAAStructTagInfo(QualType BaseTy, llvm::MDNode *AccessN, + uint64_t O); bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor); Index: lib/CodeGen/CodeGenTBAA.cpp =================================================================== --- lib/CodeGen/CodeGenTBAA.cpp (revision 178718) +++ lib/CodeGen/CodeGenTBAA.cpp (working copy) @@ -21,6 +21,7 @@ #include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" #include "clang/Frontend/CodeGenOptions.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" @@ -225,3 +226,87 @@ // For now, handle any other kind of type conservatively. return StructMetadataCache[Ty] = NULL; } + +/// Check if the given type can be handled by path-aware TBAA. +static bool isTBAAPathStruct(QualType QTy) { + if (const RecordType *TTy = QTy->getAs<RecordType>()) { + const RecordDecl *RD = TTy->getDecl()->getDefinition(); + // RD can be struct, union, class, interface or enum. + // For now, we only handle struct. + if (RD->isStruct() && !RD->hasFlexibleArrayMember()) + return true; + } + return false; +} + +llvm::MDNode * +CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) { + const Type *Ty = Context.getCanonicalType(QTy).getTypePtr(); + assert(isTBAAPathStruct(QTy)); + + if (llvm::MDNode *N = StructTypeMetadataCache[Ty]) + return N; + + if (const RecordType *TTy = QTy->getAs<RecordType>()) { + const RecordDecl *RD = TTy->getDecl()->getDefinition(); + + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + SmallVector <std::pair<uint64_t, llvm::MDNode*>, 4> Fields; + // To reduce the size of MDNode for a given struct type, we only output + // once for all the fields with the same scalar types. + // Offsets for scalar fields in the type DAG are not used. + llvm::SmallSet <llvm::MDNode*, 4> ScalarFieldTypes; + unsigned idx = 0; + for (RecordDecl::field_iterator i = RD->field_begin(), + e = RD->field_end(); i != e; ++i, ++idx) { + QualType FieldQTy = i->getType(); + llvm::MDNode *FieldNode; + if (isTBAAPathStruct(FieldQTy)) + FieldNode = getTBAAStructTypeInfo(FieldQTy); + else { + FieldNode = getTBAAInfo(FieldQTy); + // Ignore this field if the type already exists. + if (ScalarFieldTypes.count(FieldNode)) + continue; + ScalarFieldTypes.insert(FieldNode); + } + if (!FieldNode) + return StructTypeMetadataCache[Ty] = NULL; + Fields.push_back(std::make_pair( + Layout.getFieldOffset(idx) / Context.getCharWidth(), FieldNode)); + } + + // TODO: This is using the RTTI name. Is there a better way to get + // a unique string for a type? + SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + MContext.mangleCXXRTTIName(QualType(Ty, 0), Out); + Out.flush(); + // Create the struct type node with a vector of pairs (offset, type). + return StructTypeMetadataCache[Ty] = + MDHelper.createTBAAStructTypeNode(OutName, Fields); + } + + return StructMetadataCache[Ty] = NULL; +} + +llvm::MDNode * +CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode, + uint64_t Offset) { + if (!CodeGenOpts.StructPathTBAA) + return AccessNode; + + const Type *BTy = Context.getCanonicalType(BaseQTy).getTypePtr(); + TBAAPathTag PathTag = TBAAPathTag(BTy, AccessNode, Offset); + if (llvm::MDNode *N = StructTagMetadataCache[PathTag]) + return N; + + llvm::MDNode *BNode = 0; + if (isTBAAPathStruct(BaseQTy)) + BNode = getTBAAStructTypeInfo(BaseQTy); + if (!BNode) + return StructTagMetadataCache[PathTag] = AccessNode; + + return StructTagMetadataCache[PathTag] = + MDHelper.createTBAAStructTagNode(BNode, AccessNode, Offset); +} Index: lib/CodeGen/CodeGenTBAA.h =================================================================== --- lib/CodeGen/CodeGenTBAA.h (revision 178718) +++ lib/CodeGen/CodeGenTBAA.h (working copy) @@ -35,6 +35,14 @@ namespace CodeGen { class CGRecordLayout; + struct TBAAPathTag { + TBAAPathTag(const Type *B, const llvm::MDNode *A, uint64_t O) + : BaseT(B), AccessN(A), Offset(O) {} + const Type *BaseT; + const llvm::MDNode *AccessN; + uint64_t Offset; + }; + /// CodeGenTBAA - This class organizes the cross-module state that is used /// while lowering AST types to LLVM types. class CodeGenTBAA { @@ -46,8 +54,13 @@ // MDHelper - Helper for creating metadata. llvm::MDBuilder MDHelper; - /// MetadataCache - This maps clang::Types to llvm::MDNodes describing them. + /// MetadataCache - This maps clang::Types to scalar llvm::MDNodes describing + /// them. llvm::DenseMap<const Type *, llvm::MDNode *> MetadataCache; + /// This maps clang::Types to a struct node in the type DAG. + llvm::DenseMap<const Type *, llvm::MDNode *> StructTypeMetadataCache; + /// This maps TBAAPathTags to a tag node. + llvm::DenseMap<TBAAPathTag, llvm::MDNode *> StructTagMetadataCache; /// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing /// them for struct assignments. @@ -89,9 +102,49 @@ /// getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of /// the given type. llvm::MDNode *getTBAAStructInfo(QualType QTy); + + /// Get the MDNode in the type DAG for given struct type QType. + llvm::MDNode *getTBAAStructTypeInfo(QualType QType); + /// Get the tag MDNode for a given base type, the actual sclar access MDNode + /// and offset into the base type. + llvm::MDNode *getTBAAStructTagInfo(QualType BaseQType, + llvm::MDNode *AccessNode, uint64_t Offset); }; } // end namespace CodeGen } // end namespace clang +namespace llvm { + +template<> struct DenseMapInfo<clang::CodeGen::TBAAPathTag> { + static clang::CodeGen::TBAAPathTag getEmptyKey() { + return clang::CodeGen::TBAAPathTag( + DenseMapInfo<const clang::Type *>::getEmptyKey(), + DenseMapInfo<const MDNode *>::getEmptyKey(), + DenseMapInfo<uint64_t>::getEmptyKey()); + } + + static clang::CodeGen::TBAAPathTag getTombstoneKey() { + return clang::CodeGen::TBAAPathTag( + DenseMapInfo<const clang::Type *>::getTombstoneKey(), + DenseMapInfo<const MDNode *>::getTombstoneKey(), + DenseMapInfo<uint64_t>::getTombstoneKey()); + } + + static unsigned getHashValue(const clang::CodeGen::TBAAPathTag &Val) { + return DenseMapInfo<const clang::Type *>::getHashValue(Val.BaseT) ^ + DenseMapInfo<const MDNode *>::getHashValue(Val.AccessN) ^ + DenseMapInfo<uint64_t>::getHashValue(Val.Offset); + } + + static bool isEqual(const clang::CodeGen::TBAAPathTag &LHS, + const clang::CodeGen::TBAAPathTag &RHS) { + return LHS.BaseT == RHS.BaseT && + LHS.AccessN == RHS.AccessN && + LHS.Offset == RHS.Offset; + } +}; + +} // end namespace llvm + #endif Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp (revision 178718) +++ lib/Driver/Tools.cpp (working copy) @@ -2105,6 +2105,8 @@ options::OPT_fno_strict_aliasing, getToolChain().IsStrictAliasingDefault())) CmdArgs.push_back("-relaxed-aliasing"); + if (Args.hasArg(options::OPT_fstruct_path_tbaa)) + CmdArgs.push_back("-struct-path-tbaa"); if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums, false)) CmdArgs.push_back("-fstrict-enums"); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp (revision 178718) +++ lib/Frontend/CompilerInvocation.cpp (working copy) @@ -324,6 +324,7 @@ Opts.UseRegisterSizedBitfieldAccess = Args.hasArg( OPT_fuse_register_sized_bitfield_access); Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing); + Opts.StructPathTBAA = Args.hasArg(OPT_struct_path_tbaa); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); Opts.NoCommon = Args.hasArg(OPT_fno_common); Index: test/CodeGen/tbaa.cpp =================================================================== --- test/CodeGen/tbaa.cpp (revision 0) +++ test/CodeGen/tbaa.cpp (working copy) @@ -0,0 +1,217 @@ +// RUN: %clang_cc1 -O1 -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -O1 -struct-path-tbaa -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s -check-prefix=PATH +// Test TBAA metadata generated by front-end. + +#include <stdint.h> +typedef struct +{ + uint16_t f16; + uint32_t f32; + uint16_t f16_2; + uint32_t f32_2; +} StructA; +typedef struct +{ + uint16_t f16; + StructA a; + uint32_t f32; +} StructB; +typedef struct +{ + uint16_t f16; + StructB b; + uint32_t f32; +} StructC; +typedef struct +{ + uint16_t f16; + StructB b; + uint32_t f32; + uint8_t f8; +} StructD; + +typedef struct +{ + uint16_t f16; + uint32_t f32; +} StructS; +typedef struct +{ + uint16_t f16; + uint32_t f32; +} StructS2; + +uint32_t g(uint32_t *s, StructA *A, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !5 + *s = 1; + A->f32 = 4; + return *s; +} + +uint32_t g2(uint32_t *s, StructA *A, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !8 + *s = 1; + A->f16 = 4; + return *s; +} + +uint32_t g3(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9 + A->f32 = 1; + B->a.f32 = 4; + return A->f32; +} + +uint32_t g4(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !11 + A->f32 = 1; + B->a.f16 = 4; + return A->f32; +} + +uint32_t g5(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !12 + A->f32 = 1; + B->f32 = 4; + return A->f32; +} + +uint32_t g6(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !13 + A->f32 = 1; + B->a.f32_2 = 4; + return A->f32; +} + +uint32_t g7(StructA *A, StructS *S, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !14 + A->f32 = 1; + S->f32 = 4; + return A->f32; +} + +uint32_t g8(StructA *A, StructS *S, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !16 + A->f32 = 1; + S->f16 = 4; + return A->f32; +} + +uint32_t g9(StructS *S, StructS2 *S2, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !17 + S->f32 = 1; + S2->f32 = 4; + return S->f32; +} + +uint32_t g10(StructS *S, StructS2 *S2, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !19 + S->f32 = 1; + S2->f16 = 4; + return S->f32; +} + +uint32_t g11(StructC *C, StructD *D, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !20 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !22 + C->b.a.f32 = 1; + D->b.a.f32 = 4; + return C->b.a.f32; +} + +uint32_t g12(StructC *C, StructD *D, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// TODO: differentiate the two accesses. +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !9 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9 + StructB *b1 = &(C->b); + StructB *b2 = &(D->b); + // b1, b2 have different context. + b1->a.f32 = 1; + b2->a.f32 = 4; + return b1->a.f32; +} + +// CHECK: !1 = metadata !{metadata !"omnipotent char", metadata !2} +// CHECK: !2 = metadata !{metadata !"Simple C/C++ TBAA"} +// CHECK: !4 = metadata !{metadata !"int", metadata !1} +// CHECK: !5 = metadata !{metadata !"short", metadata !1} + +// PATH: !1 = metadata !{metadata !"omnipotent char", metadata !2} +// PATH: !4 = metadata !{metadata !"int", metadata !1} +// PATH: !5 = metadata !{metadata !6, metadata !4, i64 4} +// PATH: !6 = metadata !{metadata !"_ZTS7StructA", i64 0, metadata !7, i64 4, metadata !4} +// PATH: !7 = metadata !{metadata !"short", metadata !1} +// PATH: !8 = metadata !{metadata !6, metadata !7, i64 0} +// PATH: !9 = metadata !{metadata !10, metadata !4, i64 8} +// PATH: !10 = metadata !{metadata !"_ZTS7StructB", i64 0, metadata !7, i64 4, metadata !6, i64 20, metadata !4} +// PATH: !11 = metadata !{metadata !10, metadata !7, i64 4} +// PATH: !12 = metadata !{metadata !10, metadata !4, i64 20} +// PATH: !13 = metadata !{metadata !10, metadata !4, i64 16} +// PATH: !14 = metadata !{metadata !15, metadata !4, i64 4} +// PATH: !15 = metadata !{metadata !"_ZTS7StructS", i64 0, metadata !7, i64 4, metadata !4} +// PATH: !16 = metadata !{metadata !15, metadata !7, i64 0} +// PATH: !17 = metadata !{metadata !18, metadata !4, i64 4} +// PATH: !18 = metadata !{metadata !"_ZTS8StructS2", i64 0, metadata !7, i64 4, metadata !4} +// PATH: !19 = metadata !{metadata !18, metadata !7, i64 0} +// PATH: !20 = metadata !{metadata !21, metadata !4, i64 12} +// PATH: !21 = metadata !{metadata !"_ZTS7StructC", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4} +// PATH: !22 = metadata !{metadata !23, metadata !4, i64 12} +// PATH: !23 = metadata !{metadata !"_ZTS7StructD", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4, i64 32, metadata !1} git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178784 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Remove the unused MemoryBuffers, no functionality change.Argyrios Kyrtzidis
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178780 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Fix bug discovered with address sanitizer.Daniel Jasper
Now, this works again with an empty stack. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178779 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Objective-C: Issue deprecated warning when using a Fariborz Jahanian
deprecated typedef to subclass or invoke a class method. // rdar://13569424 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178775 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Use isExternalLinkage instead of hasExternalLinkage.Rafael Espindola
Having these not be the same makes an easy to misuse API. We should audit the uses and probably rename to something like foo->hasExternalLinkage(): The c++ standard one. That is UniqueExternalLinkage or ExternalLinkage. foo->hasUniqueExternalLinkage(): Is UniqueExternalLinkage. foo->hasCogeGenExternalLinkage(): Is ExternalLinkage. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178768 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Make helpers static & 80 cols.Benjamin Kramer
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178767 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Fix a recent linkage regression.Rafael Espindola
Now that we don't have a semantic storage class, use the linkage. Thanks to Bruce Stephens for reporting this. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178766 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Plumb through the -fsplit-stack option using the existing backendEric Christopher
support. Caveat: Other than the existing segmented stacks support, no claims are made of this working. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178744 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Revert r177948. We decided that we do not want ObjC property redeclarations ↵Ted Kremenek
to inherit "deprecated". git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178743 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Add hasExternalLinkageUncached back with the test that Richard provided, butRafael Espindola
keep the call at the current location. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178741 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Avoid computing the linkage instead of avoiding caching it.Rafael Espindola
This mostly reverts 178733, but keeps the tests. I don't claim to understand how hidden sub modules work or when we need to see them (is that documented?), but this has the same semantics and avoids adding hasExternalLinkageUncached which has the same foot gun potential as the old hasExternalLinkage. Last but not least, not computing linkage when it is not needed is more efficient. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178739 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Add tests that build modules for our builtin headers, and fix two buglets ↵Richard Smith
exposed by doing so. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178736 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Fix linkage related crash.Rafael Espindola
This test was exactly the opposite of what it should be. We should check if there old decl has linkage (where it makes sense) and if the new decl has the extern keyword. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178735 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Fix 41 of the 61 tests which fail with modules enabled: we were computing andRichard Smith
caching the linkage for a declaration before we set up its redeclaration chain, when determining whether a declaration could be a redeclaration of something from an unimported submodule. We actually want to look at the declaration as if it were not a redeclaration here, so compute the linkage but don't cache it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178733 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Be sure to check ARC conventions on the implicit method declarationsJohn McCall
of a property just in case the property's getter happens to be +1. We won't synthesize a getter for such a property, but we will allow the user to define a +1 method for it. rdar://13115896 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178731 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Protect the values of array and dictionary literals from theJohn McCall
ARC optimizer while they're held in local unsafe buffers. Based on a patch by Jesse Rusak! rdar://13573224 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178721 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-04Make the ObjC attributes diagnostics a bit more informative.Nico Weber
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178720 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03Update OpenCL comments to mention spec section and version.Tanya Lattner
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178716 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03<rdar://problem/13560075> Teach name lookup for builtin names to find hidden ↵Douglas Gregor
declarations. Normal name lookup ignores any hidden declarations. When name lookup for builtin declarations fails, we just synthesize a new declaration at the point of use. With modules, this could lead to multiple declarations of the same builtin, if one came from a (hidden) submodule that was later made visible. Teach name lookup to always find builtin names, so we don't create these redundant declarations in the first place. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178711 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03Pare back r164351 somewhat. The problem that change was addressing was that weRichard Smith
don't serialize a lookup map for the translation unit outside C++ mode, so we can't tell when lookup within the TU needs to look within modules. Only apply the fix outside C++ mode, and only to the translation unit. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178706 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03[analyzer] Allow tracknullOrUndef look through the ternary operator even ↵Anna Zaks
when condition is unknown Improvement of r178684 and r178685. Jordan has pointed out that I should not rely on the value of the condition to know which expression branch has been taken. It will not work in cases the branch condition is an unknown value (ex: we do not track the constraints for floats). The better way of doing this would be to find out if the current node is the right or left successor of the node that has the ternary operator as a terminator (which is how this is done in other places, like ConditionBRVisitor). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178701 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03[preprocessor] Minor optimization following r178671.Argyrios Kyrtzidis
Don't bother looking for parameter index of 'B' token if 'A' is not a parameter. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178699 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03Complain about attempts to befriend declarations via a usingJohn McCall
declaration. Patch by Stephen Lin! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178698 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03[analyzer] Correctly handle destructors for lifetime-extended temporaries.Jordan Rose
The lifetime of a temporary can be extended when it is immediately bound to a local reference: const Value &MyVal = Value("temporary"); In this case, the temporary object's lifetime is extended for the entire scope of the reference; at the end of the scope it is destroyed. The analyzer was modeling this improperly in two ways: - Since we don't model temporary constructors just yet, we create a fake temporary region when it comes time to "materialize" a temporary into a real object (lvalue). This wasn't taking base casts into account when the bindings being materialized was Unknown; now it always respects base casts except when the temporary region is itself a pointer. - When actually destroying the region, the analyzer did not actually load from the reference variable -- it was basically destroying the reference instead of its referent. Now it does do the load. This will be more useful whenever we finally start modeling temporaries, or at least those that get bound to local reference variables. <rdar://problem/13552274> git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178697 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03[analyzer] Rename “Mac OS X API”, “Mac OS API” -> “API Misuse ↵Anna Zaks
(Apple)” As they are relevant on both Mac and iOS. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178687 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03[analyzer] Warn when nil receiver results in forming null referenceAnna Zaks
This also allows us to ensure IDC/return null suppression gets triggered in such cases. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178686 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03[analyzer] make peelOffOuterExpr in BugReporterVisitors recursively peel off ↵Anna Zaks
select Exprs git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178685 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03[analyzer] Properly handle the ternary operator in trackNullOrUndefValueAnna Zaks
1) Look for the node where the condition expression is live when checking if it is constrained to true or false. 2) Fix a bug in ProgramState::isNull, which was masking the problem. When the expression is not a symbol (,which is the case when it is Unknown) return unconstrained value, instead of value constrained to “false”! (Thankfully other callers of isNull have not been effected by the bug.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178684 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03[analyzer] Fix typo.Anna Zaks
Thanks Jordan! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178683 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03Add 178663 back.Rafael Espindola
http://lab.llvm.org:8011/builders/clang-x86_64-darwin10-gdb went back green before it processed the reverted 178663, so it could not have been the culprit. Revert "Revert 178663." This reverts commit 4f8a3eb2ce5d4ba422483439e20c8cbb4d953a41. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178682 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03Revert 178663.Rafael Espindola
Looks like it broke http://lab.llvm.org:8011/builders/clang-x86_64-darwin10-gdb Revert "Don't compute a patched/semantic storage class." This reverts commit 8f187f62cb0487d31bc4afdfcd47e11fe9a51d05. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178681 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03Objective-C modern rewriter. Fixes a bugFariborz Jahanian
rewriting typedef for a qualified object type and also when two declarations happen to be on the same line. // rdar://13562505 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178680 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03[preprocessor] Allow comparing two macro definitions syntactically instead ↵Argyrios Kyrtzidis
of only lexically. Syntactically means the function macro parameter names do not need to use the same identifiers in order for the definitions to be considered identical. Syntactic equivalence is a microsoft extension for macro redefinitions and we'll also use this kind of comparison to check for ambiguous macros coming from modules. rdar://13562254 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178671 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03Emit a nicer diagnostic for misplaced attributes on ObjC directives.Nico Weber
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178670 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03Give the default CorrectionCandidateCallback::ValidateCandidate someKaelyn Uhrain
smarts so that it doesn't approve of keywords and/or type names when it knows (based on its flags) that those kinds of corrections are not wanted. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178668 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03Don't compute a patched/semantic storage class.Rafael Espindola
For variables and functions clang used to store two storage classes. The one "as written" in the code and a patched one, which, for example, propagates static to the following decls. This apparently is from the days clang lacked linkage computation. It is now redundant and this patch removes it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178663 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03Improve formatting of for loops and multi-variable DeclStmts.Daniel Jasper
This combines several related changes: a) Don't break before after the variable types in for loops with a single variable. b) Better indent DeclStmts defining multiple variables. Before: bool aaaaaaaaaaaaaaaaaaaaaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaa), bbbbbbbbbbbbbbbbbbbbbbbbb = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(bbbbbbbbbbbbbbbb); for (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaa = aaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaa; aaaaaaaaaaa != aaaaaaaaaaaaaaaaaaa; ++aaaaaaaaaaa) { } After: bool aaaaaaaaaaaaaaaaaaaaaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaa), bbbbbbbbbbbbbbbbbbbbbbbbb = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(bbbbbbbbbbbbbbbb); for (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaa = aaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaa; aaaaaaaaaaa != aaaaaaaaaaaaaaaaaaa; ++aaaaaaaaaaa) { } git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178641 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03Even better way to handle comments adjacent to preprocessor directives.Alexander Kornienko
Summary: It turns out that we don't need to store CommentsBeforeNextToken in the line state, but rather flush them before we start parsing preprocessor directives. This fixes wrong comment indentation in code blocks in macro calls (the test is included). Reviewers: klimek Reviewed By: klimek CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D617 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178638 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03Enable use of _Static_assert inside structs and unions in C11 mode (as per ↵Andy Gibbs
C11 6.7.2.1p1). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178632 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03Assert that Parser::ParseStructUnionBody is not called for C++ code.Andy Gibbs
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178631 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-03Cleanup, add comments and address review comments.Daniel Jasper
No functional changes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178626 91177308-0d34-0410-b5e6-96231b3b80d8