diff options
229 files changed, 2977 insertions, 1700 deletions
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py index c37c69b79b38..f4409aec3325 100644 --- a/bindings/python/clang/cindex.py +++ b/bindings/python/clang/cindex.py @@ -187,12 +187,56 @@ class Diagnostic(object): Error = 3 Fatal = 4 - def __init__(self, severity, location, spelling, ranges, fixits): - self.severity = severity - self.location = location - self.spelling = spelling - self.ranges = ranges - self.fixits = fixits + def __init__(self, ptr): + self.ptr = ptr + + def __del__(self): + _clang_disposeDiagnostic(self.ptr) + + @property + def severity(self): + return _clang_getDiagnosticSeverity(self.ptr) + + @property + def location(self): + return _clang_getDiagnosticLocation(self.ptr) + + @property + def spelling(self): + return _clang_getDiagnosticSpelling(self.ptr) + + @property + def ranges(self): + class RangeIterator: + def __init__(self, diag): + self.diag = diag + + def __len__(self): + return int(_clang_getDiagnosticNumRanges(self.diag)) + + def __getitem__(self, key): + return _clang_getDiagnosticRange(self.diag, key) + + return RangeIterator(self.ptr) + + @property + def fixits(self): + class FixItIterator: + def __init__(self, diag): + self.diag = diag + + def __len__(self): + return int(_clang_getDiagnosticNumFixIts(self.diag)) + + def __getitem__(self, key): + range = SourceRange() + value = _clang_getDiagnosticFixIt(self.diag, key, byref(range)) + if len(value) == 0: + raise IndexError + + return FixIt(range, value) + + return FixItIterator(self.ptr) def __repr__(self): return "<Diagnostic severity %r, location %r, spelling %r>" % ( @@ -539,8 +583,16 @@ class _CXUnsavedFile(Structure): ## Diagnostic Conversion ## -# Diagnostic objects are temporary, we must extract all the information from the -# diagnostic object when it is passed to the callback. +_clang_getNumDiagnostics = lib.clang_getNumDiagnostics +_clang_getNumDiagnostics.argtypes = [c_object_p] +_clang_getNumDiagnostics.restype = c_uint + +_clang_getDiagnostic = lib.clang_getDiagnostic +_clang_getDiagnostic.argtypes = [c_object_p, c_uint] +_clang_getDiagnostic.restype = c_object_p + +_clang_disposeDiagnostic = lib.clang_disposeDiagnostic +_clang_disposeDiagnostic.argtypes = [c_object_p] _clang_getDiagnosticSeverity = lib.clang_getDiagnosticSeverity _clang_getDiagnosticSeverity.argtypes = [c_object_p] @@ -567,67 +619,10 @@ _clang_getDiagnosticNumFixIts = lib.clang_getDiagnosticNumFixIts _clang_getDiagnosticNumFixIts.argtypes = [c_object_p] _clang_getDiagnosticNumFixIts.restype = c_uint -_clang_getDiagnosticFixItKind = lib.clang_getDiagnosticFixItKind -_clang_getDiagnosticFixItKind.argtypes = [c_object_p, c_uint] -_clang_getDiagnosticFixItKind.restype = c_int - -_clang_getDiagnosticFixItInsertion = lib.clang_getDiagnosticFixItInsertion -_clang_getDiagnosticFixItInsertion.argtypes = [c_object_p, c_uint, - POINTER(SourceLocation)] -_clang_getDiagnosticFixItInsertion.restype = _CXString -_clang_getDiagnosticFixItInsertion.errcheck = _CXString.from_result - -_clang_getDiagnosticFixItRemoval = lib.clang_getDiagnosticFixItRemoval -_clang_getDiagnosticFixItRemoval.argtypes = [c_object_p, c_uint, - POINTER(SourceLocation)] -_clang_getDiagnosticFixItRemoval.restype = _CXString -_clang_getDiagnosticFixItRemoval.errcheck = _CXString.from_result - -_clang_getDiagnosticFixItReplacement = lib.clang_getDiagnosticFixItReplacement -_clang_getDiagnosticFixItReplacement.argtypes = [c_object_p, c_uint, - POINTER(SourceRange)] -_clang_getDiagnosticFixItReplacement.restype = _CXString -_clang_getDiagnosticFixItReplacement.errcheck = _CXString.from_result - -def _convert_fixit(diag_ptr, index): - # We normalize all the fix-its to a single representation, this is more - # convenient. - # - # FIXME: Push this back into API? It isn't exactly clear what the - # SourceRange semantics are, we should make sure we can represent an empty - # range. - kind = _clang_getDiagnosticFixItKind(diag_ptr, index) - range = None - value = None - if kind == 0: # insertion - location = SourceLocation() - value = _clang_getDiagnosticFixItInsertion(diag_ptr, index, - byref(location)) - range = SourceRange.from_locations(location, location) - elif kind == 1: # removal - range = _clang_getDiagnosticFixItRemoval(diag_ptr, index) - value = '' - else: # replacement - assert kind == 2 - range = SourceRange() - value = _clang_getDiagnosticFixItReplacement(diag_ptr, index, - byref(range)) - return FixIt(range, value) - -def _convert_diag(diag_ptr, diag_list): - severity = _clang_getDiagnosticSeverity(diag_ptr) - loc = _clang_getDiagnosticLocation(diag_ptr) - spelling = _clang_getDiagnosticSpelling(diag_ptr) - - # Diagnostic ranges. - num_ranges = _clang_getDiagnosticNumRanges(diag_ptr) - ranges = [_clang_getDiagnosticRange(diag_ptr, i) - for i in range(num_ranges)] - - fixits = [_convert_fixit(diag_ptr, i) - for i in range(_clang_getDiagnosticNumFixIts(diag_ptr))] - - diag_list.append(Diagnostic(severity, loc, spelling, ranges, fixits)) +_clang_getDiagnosticFixIt = lib.clang_getDiagnosticFixIt +_clang_getDiagnosticFixIt.argtypes = [c_object_p, c_uint, POINTER(SourceRange)] +_clang_getDiagnosticFixIt.restype = _CXString +_clang_getDiagnosticFixIt.errcheck = _CXString.from_result ### @@ -645,18 +640,14 @@ class Index(ClangObject): Parameters: excludeDecls -- Exclude local declarations from translation units. """ - return Index(Index_create(excludeDecls)) + return Index(Index_create(excludeDecls, 0)) def __del__(self): Index_dispose(self) def read(self, path): """Load the translation unit from the given AST file.""" - # FIXME: In theory, we could support streaming diagnostics. It's hard to - # integrate this into the API cleanly, however. Resolve. - diags = [] - ptr = TranslationUnit_read(self, path, - Diagnostic_callback(_convert_diag), diags) + ptr = TranslationUnit_read(self, path) return TranslationUnit(ptr) if ptr else None def parse(self, path, args = [], unsaved_files = []): @@ -687,13 +678,9 @@ class Index(ClangObject): unsaved_files_array[i].name = name unsaved_files_array[i].contents = value unsaved_files_array[i].length = len(value) - # FIXME: In theory, we could support streaming diagnostics. It's hard to - # integrate this into the API cleanly, however. Resolve. - diags = [] ptr = TranslationUnit_parse(self, path, len(args), arg_array, - len(unsaved_files), unsaved_files_array, - Diagnostic_callback(_convert_diag), diags) - return TranslationUnit(ptr, diags) if ptr else None + len(unsaved_files), unsaved_files_array) + return TranslationUnit(ptr) if ptr else None class TranslationUnit(ClangObject): @@ -702,9 +689,8 @@ class TranslationUnit(ClangObject): provides read-only access to its top-level declarations. """ - def __init__(self, ptr, diagnostics): + def __init__(self, ptr): ClangObject.__init__(self, ptr) - self.diagnostics = diagnostics def __del__(self): TranslationUnit_dispose(self) @@ -738,6 +724,26 @@ class TranslationUnit(ClangObject): includes) return iter(includes) + @property + def diagnostics(self): + """ + Return an iterable (and indexable) object containing the diagnostics. + """ + class DiagIterator: + def __init__(self, tu): + self.tu = tu + + def __len__(self): + return int(_clang_getNumDiagnostics(self.tu)) + + def __getitem__(self, key): + diag = _clang_getDiagnostic(self.tu, key) + if not diag: + raise IndexError + return Diagnostic(diag) + + return DiagIterator(self) + class File(ClangObject): """ The File class represents a particular source file that is part of a @@ -876,24 +882,20 @@ Cursor_visit.restype = c_uint # Index Functions Index_create = lib.clang_createIndex -Index_create.argtypes = [c_int] +Index_create.argtypes = [c_int, c_int] Index_create.restype = c_object_p Index_dispose = lib.clang_disposeIndex Index_dispose.argtypes = [Index] # Translation Unit Functions -Diagnostic_callback = CFUNCTYPE(None, c_object_p, py_object) - TranslationUnit_read = lib.clang_createTranslationUnit -TranslationUnit_read.argtypes = [Index, c_char_p, - Diagnostic_callback, py_object] +TranslationUnit_read.argtypes = [Index, c_char_p] TranslationUnit_read.restype = c_object_p TranslationUnit_parse = lib.clang_createTranslationUnitFromSourceFile TranslationUnit_parse.argtypes = [Index, c_char_p, c_int, c_void_p, - c_int, c_void_p, - Diagnostic_callback, py_object] + c_int, c_void_p] TranslationUnit_parse.restype = c_object_p TranslationUnit_cursor = lib.clang_getTranslationUnitCursor diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 7bc290d88f4e..da186f6424de 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -888,6 +888,12 @@ CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind); */ CINDEX_LINKAGE unsigned clang_isTranslationUnit(enum CXCursorKind); +/*** + * \brief Determine whether the given cursor represents a currently + * unexposed piece of the AST (e.g., CXCursor_UnexposedStmt). + */ +CINDEX_LINKAGE unsigned clang_isUnexposed(enum CXCursorKind); + /** * \brief Describe the linkage of the entity referred to by a cursor. */ diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 0838a3d0ebe6..cf9aa50af2a1 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -405,6 +405,8 @@ private: /// getExtQualType - Return a type with extended qualifiers. QualType getExtQualType(const Type *Base, Qualifiers Quals); + QualType getTypeDeclTypeSlow(const TypeDecl *Decl); + public: /// getAddSpaceQualType - Return the uniqued reference to the type for an /// address space qualified type with the specified type and address space. @@ -580,12 +582,26 @@ public: /// getTypeDeclType - Return the unique reference to the type for /// the specified type declaration. - QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl* PrevDecl=0); + QualType getTypeDeclType(const TypeDecl *Decl, + const TypeDecl *PrevDecl = 0) { + assert(Decl && "Passed null for Decl param"); + if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); + + if (PrevDecl) { + assert(PrevDecl->TypeForDecl && "previous decl has no TypeForDecl"); + Decl->TypeForDecl = PrevDecl->TypeForDecl; + return QualType(PrevDecl->TypeForDecl, 0); + } + + return getTypeDeclTypeSlow(Decl); + } /// getTypedefType - Return the unique reference to the type for the /// specified typename decl. QualType getTypedefType(const TypedefDecl *Decl); + QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST); + QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced, QualType Replacement); @@ -602,6 +618,11 @@ public: const TemplateArgumentListInfo &Args, QualType Canon = QualType()); + TypeSourceInfo * + getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc, + const TemplateArgumentListInfo &Args, + QualType Canon = QualType()); + QualType getQualifiedNameType(NestedNameSpecifier *NNS, QualType NamedType); QualType getTypenameType(NestedNameSpecifier *NNS, diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 91aeff3439b3..bd9f01b0b5ef 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -1429,7 +1429,6 @@ class TypeDecl : public NamedDecl { friend class DeclContext; friend class TagDecl; friend class TemplateTypeParmDecl; - friend class ClassTemplateSpecializationDecl; friend class TagType; protected: diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 26656bf30a65..889e0d6c1be8 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -136,8 +136,12 @@ private: /// in, inout, etc. unsigned objcDeclQualifier : 6; - // Type of this method. + // Result type of this method. QualType MethodDeclType; + + // Type source information for the result type. + TypeSourceInfo *ResultTInfo; + /// ParamInfo - List of pointers to VarDecls for the formal parameters of this /// Method. ObjCList<ParmVarDecl> ParamInfo; @@ -158,6 +162,7 @@ private: ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, QualType T, + TypeSourceInfo *ResultTInfo, DeclContext *contextDecl, bool isInstance = true, bool isVariadic = false, @@ -168,7 +173,7 @@ private: IsInstance(isInstance), IsVariadic(isVariadic), IsSynthesized(isSynthesized), DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), - MethodDeclType(T), + MethodDeclType(T), ResultTInfo(ResultTInfo), EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {} virtual ~ObjCMethodDecl() {} @@ -186,7 +191,9 @@ public: static ObjCMethodDecl *Create(ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, - QualType T, DeclContext *contextDecl, + QualType T, + TypeSourceInfo *ResultTInfo, + DeclContext *contextDecl, bool isInstance = true, bool isVariadic = false, bool isSynthesized = false, @@ -220,6 +227,9 @@ public: QualType getResultType() const { return MethodDeclType; } void setResultType(QualType T) { MethodDeclType = T; } + TypeSourceInfo *getResultTypeSourceInfo() const { return ResultTInfo; } + void setResultTypeSourceInfo(TypeSourceInfo *TInfo) { ResultTInfo = TInfo; } + // Iterator access to formal parameters. unsigned param_size() const { return ParamInfo.size(); } typedef ObjCList<ParmVarDecl>::iterator param_iterator; diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index ced174716c7a..560ce46ede7c 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -771,6 +771,10 @@ class ClassTemplateSpecializationDecl llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *> SpecializedTemplate; + /// \brief The type-as-written of an explicit template specialization. + /// Does not apply to implicit specializations. + TypeSourceInfo *TypeAsWritten; + /// \brief The template arguments used to describe this specialization. TemplateArgumentList TemplateArgs; @@ -883,8 +887,14 @@ public: /// \brief Sets the type of this specialization as it was written by /// the user. This will be a class template specialization type. - void setTypeAsWritten(QualType T) { - TypeForDecl = T.getTypePtr(); + void setTypeAsWritten(TypeSourceInfo *T) { + TypeAsWritten = T; + } + + /// \brief Gets the type of this specialization as it was written by + /// the user, if it was so written. + TypeSourceInfo *getTypeAsWritten() const { + return TypeAsWritten; } void Profile(llvm::FoldingSetNodeID &ID) const { @@ -921,6 +931,7 @@ class ClassTemplatePartialSpecializationDecl TemplateParameterList* TemplateParams; /// \brief The source info for the template arguments as written. + /// FIXME: redundant with TypeAsWritten? TemplateArgumentLoc *ArgsAsWritten; unsigned NumArgsAsWritten; @@ -954,6 +965,7 @@ public: ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, const TemplateArgumentListInfo &ArgInfos, + QualType CanonInjectedType, ClassTemplatePartialSpecializationDecl *PrevDecl); /// Get the list of template parameters @@ -1139,8 +1151,8 @@ public: /// the type \p T, or NULL if no such partial specialization exists. ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T); - /// \brief Retrieve the type of the injected-class-name for this - /// class template. + /// \brief Retrieve the template specialization type of the + /// injected-class-name for this class template. /// /// The injected-class-name for a class template \c X is \c /// X<template-args>, where \c template-args is formed from the @@ -1153,7 +1165,7 @@ public: /// typedef array this_type; // "array" is equivalent to "array<T, N>" /// }; /// \endcode - QualType getInjectedClassNameType(ASTContext &Context); + QualType getInjectedClassNameSpecialization(ASTContext &Context); /// \brief Retrieve the member class template that this class template was /// derived from. diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index df39b535eb3e..6f43973a3e1d 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -347,6 +347,9 @@ class ObjCMessageExpr : public Expr { // message expression. unsigned NumArgs; + /// \brief The location of the class name in a class message. + SourceLocation ClassNameLoc; + // A unigue name for this message. Selector SelName; @@ -367,7 +370,8 @@ class ObjCMessageExpr : public Expr { public: /// This constructor is used to represent class messages where the /// ObjCInterfaceDecl* of the receiver is not known. - ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName, Selector selInfo, + ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName, + SourceLocation clsNameLoc, Selector selInfo, QualType retType, ObjCMethodDecl *methDecl, SourceLocation LBrac, SourceLocation RBrac, Expr **ArgExprs, unsigned NumArgs); @@ -375,7 +379,8 @@ public: /// This constructor is used to represent class messages where the /// ObjCInterfaceDecl* of the receiver is known. // FIXME: clsName should be typed to ObjCInterfaceType - ObjCMessageExpr(ASTContext &C, ObjCInterfaceDecl *cls, Selector selInfo, + ObjCMessageExpr(ASTContext &C, ObjCInterfaceDecl *cls, + SourceLocation clsNameLoc, Selector selInfo, QualType retType, ObjCMethodDecl *methDecl, SourceLocation LBrac, SourceLocation RBrac, Expr **ArgExprs, unsigned NumArgs); @@ -411,7 +416,24 @@ public: ObjCMethodDecl *getMethodDecl() { return MethodProto; } void setMethodDecl(ObjCMethodDecl *MD) { MethodProto = MD; } - typedef std::pair<ObjCInterfaceDecl*, IdentifierInfo*> ClassInfo; + /// \brief Describes the class receiver of a message send. + struct ClassInfo { + /// \brief The interface declaration for the class that is + /// receiving the message. May be NULL. + ObjCInterfaceDecl *Decl; + + /// \brief The name of the class that is receiving the + /// message. This will never be NULL. + IdentifierInfo *Name; + + /// \brief The source location of the class name. + SourceLocation Loc; + + ClassInfo() : Decl(0), Name(0), Loc() { } + + ClassInfo(ObjCInterfaceDecl *Decl, IdentifierInfo *Name, SourceLocation Loc) + : Decl(Decl), Name(Name), Loc(Loc) { } + }; /// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl* /// and IdentifierInfo* of the invoked class. Both can be NULL if this @@ -423,7 +445,7 @@ public: /// getClassName - For class methods, this returns the invoked class, /// and returns NULL otherwise. For instance methods, use getReceiver. IdentifierInfo *getClassName() const { - return getClassInfo().second; + return getClassInfo().Name; } /// getNumArgs - Return the number of actual arguments to this call. diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index 0635ec5dcd51..587b5c2b40f7 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -36,7 +36,7 @@ struct PrintingPolicy { /// \brief Create a default printing policy for C. PrintingPolicy(const LangOptions &LO) : Indentation(2), LangOpts(LO), SuppressSpecifiers(false), - SuppressTag(false), SuppressTagKind(false), SuppressScope(false), + SuppressTag(false), SuppressScope(false), Dump(false), ConstantArraySizeAsWritten(false) { } /// \brief The number of spaces to use to indent each line. @@ -71,10 +71,6 @@ struct PrintingPolicy { /// \endcode bool SuppressTag : 1; - /// \brief If we are printing a tag type, suppresses printing of the - /// kind of tag, e.g., "struct", "union", "enum". - bool SuppressTagKind : 1; - /// \brief Suppresses printing of scope specifiers. bool SuppressScope : 1; @@ -101,6 +97,7 @@ struct PrintingPolicy { /// char a[9] = "A string"; /// \endcode bool ConstantArraySizeAsWritten : 1; + }; } // end namespace clang diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index e8d1788ded88..cd25969db0b0 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -128,47 +128,24 @@ private: friend class ASTContext; friend class ASTRecordLayoutBuilder; - ASTRecordLayout(uint64_t size, unsigned alignment, unsigned datasize, - const uint64_t *fieldoffsets, unsigned fieldcount) - : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment), - FieldCount(fieldcount), CXXInfo(0) { - if (FieldCount > 0) { - FieldOffsets = new uint64_t[FieldCount]; - for (unsigned i = 0; i < FieldCount; ++i) - FieldOffsets[i] = fieldoffsets[i]; - } - } + ASTRecordLayout(ASTContext &Ctx, uint64_t size, unsigned alignment, + unsigned datasize, const uint64_t *fieldoffsets, + unsigned fieldcount); // Constructor for C++ records. - ASTRecordLayout(uint64_t size, unsigned alignment, uint64_t datasize, + ASTRecordLayout(ASTContext &Ctx, + uint64_t size, unsigned alignment, uint64_t datasize, const uint64_t *fieldoffsets, unsigned fieldcount, uint64_t nonvirtualsize, unsigned nonvirtualalign, const PrimaryBaseInfo &PrimaryBase, const std::pair<const CXXRecordDecl *, uint64_t> *bases, unsigned numbases, const std::pair<const CXXRecordDecl *, uint64_t> *vbases, - unsigned numvbases) - : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment), - FieldCount(fieldcount), CXXInfo(new CXXRecordLayoutInfo) { - if (FieldCount > 0) { - FieldOffsets = new uint64_t[FieldCount]; - for (unsigned i = 0; i < FieldCount; ++i) - FieldOffsets[i] = fieldoffsets[i]; - } + unsigned numvbases); - CXXInfo->PrimaryBase = PrimaryBase; - CXXInfo->NonVirtualSize = nonvirtualsize; - CXXInfo->NonVirtualAlign = nonvirtualalign; - for (unsigned i = 0; i != numbases; ++i) - CXXInfo->BaseOffsets[bases[i].first] = bases[i].second; - for (unsigned i = 0; i != numvbases; ++i) - CXXInfo->VBaseOffsets[vbases[i].first] = vbases[i].second; - } + ~ASTRecordLayout() {} - ~ASTRecordLayout() { - delete [] FieldOffsets; - delete CXXInfo; - } + void Destroy(ASTContext &Ctx); ASTRecordLayout(const ASTRecordLayout&); // DO NOT IMPLEMENT void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index bd8a6bc8467c..111be5562199 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -2440,6 +2440,47 @@ public: static bool classof(const TemplateSpecializationType *T) { return true; } }; +/// \brief The injected class name of a C++ class template. Used to +/// record that a type was spelled with a bare identifier rather than +/// as a template-id; the equivalent for non-templated classes is just +/// RecordType. +/// +/// For consistency, template instantiation turns these into RecordTypes. +/// +/// The desugared form is always a unqualified TemplateSpecializationType. +/// The canonical form is always either a TemplateSpecializationType +/// (when dependent) or a RecordType (otherwise). +class InjectedClassNameType : public Type { + CXXRecordDecl *Decl; + + QualType UnderlyingType; + + friend class ASTContext; // ASTContext creates these. + InjectedClassNameType(CXXRecordDecl *D, QualType TST, QualType Canon) + : Type(InjectedClassName, Canon, Canon->isDependentType()), + Decl(D), UnderlyingType(TST) { + assert(isa<TemplateSpecializationType>(TST)); + assert(!TST.hasQualifiers()); + assert(TST->getCanonicalTypeInternal() == Canon); + } + +public: + QualType getUnderlyingType() const { return UnderlyingType; } + const TemplateSpecializationType *getUnderlyingTST() const { + return cast<TemplateSpecializationType>(UnderlyingType.getTypePtr()); + } + + CXXRecordDecl *getDecl() const { return Decl; } + + bool isSugared() const { return true; } + QualType desugar() const { return UnderlyingType; } + + static bool classof(const Type *T) { + return T->getTypeClass() == InjectedClassName; + } + static bool classof(const InjectedClassNameType *T) { return true; } +}; + /// \brief Represents a type that was referred to via a qualified /// name, e.g., N::M::type. /// diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 6fb51edb76f9..27659bd02f97 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -488,6 +488,14 @@ public: } }; +/// \brief Wrapper for source info for injected class names of class +/// templates. +class InjectedClassNameTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + InjectedClassNameTypeLoc, + InjectedClassNameType> { +}; + /// \brief Wrapper for source info for unresolved typename using decls. class UnresolvedUsingTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 8187caddc6aa..e75202e50abf 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -91,6 +91,7 @@ DEPENDENT_TYPE(TemplateTypeParm, Type) NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) NON_CANONICAL_TYPE(QualifiedName, Type) +NON_CANONICAL_TYPE(InjectedClassName, Type) DEPENDENT_TYPE(Typename, Type) TYPE(ObjCInterface, Type) TYPE(ObjCObjectPointer, Type) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 5d80528817c4..880b4bab6e26 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -284,6 +284,9 @@ BUILTIN(__builtin_ia32_roundps, "V4fV4fi", "") BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fi", "") BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2di", "") BUILTIN(__builtin_ia32_roundpd, "V2dV2di", "") +BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fi", "") +BUILTIN(__builtin_ia32_dppd, "V2dV2dV2di", "") +BUILTIN(__builtin_ia32_movntdqa, "V2LLiV2LLi*", "") #undef BUILTIN diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 9175bef60f1e..2bce12db535b 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -90,6 +90,7 @@ def warn_drv_missing_resource_library : Warning< def warn_drv_conflicting_deployment_targets : Warning< "conflicting deployment targets, both MACOSX_DEPLOYMENT_TARGET '%0' and IPHONEOS_DEPLOYMENT_TARGET '%1' are present in environment">; def warn_drv_treating_input_as_cxx : Warning< - "treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">; + "treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">, + InGroup<Deprecated>; } diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index c3c0cf5d0c7c..17bad64e9c82 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -24,7 +24,6 @@ def AddressOfTemporary : DiagGroup<"address-of-temporary">; def : DiagGroup<"aggregate-return">; def : DiagGroup<"attributes">; def : DiagGroup<"bad-function-cast">; -def BadLiteral : DiagGroup<"bad-literal">; def : DiagGroup<"c++-compat">; def : DiagGroup<"cast-align">; def : DiagGroup<"cast-qual">; @@ -32,6 +31,7 @@ def : DiagGroup<"char-align">; def Comment : DiagGroup<"comment">; def : DiagGroup<"ctor-dtor-privacy">; def : DiagGroup<"declaration-after-statement">; +def Deprecated : DiagGroup<"deprecated">; def : DiagGroup<"disabled-optimization">; def : DiagGroup<"discard-qual">; def : DiagGroup<"div-by-zero">; @@ -48,7 +48,8 @@ def : DiagGroup<"init-self">; def : DiagGroup<"inline">; def : DiagGroup<"int-to-pointer-cast">; def : DiagGroup<"invalid-pch">; -def : DiagGroup<"missing-braces">; +def LiteralRange : DiagGroup<"literal-range">; +def MissingBraces : DiagGroup<"missing-braces">; def : DiagGroup<"missing-declarations">; def : DiagGroup<"missing-format-attribute">; def : DiagGroup<"missing-include-dirs">; @@ -156,6 +157,7 @@ def Most : DiagGroup<"most", [ Format, Implicit, MismatchedTags, + MissingBraces, MultiChar, ReturnType, Switch, @@ -181,4 +183,4 @@ def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment // A warning group for warnings that we want to have on by default in clang, // but which aren't on by default in GCC. def NonGCC : DiagGroup<"non-gcc", - [SignCompare, Conversion, BadLiteral]>; + [SignCompare, Conversion, LiteralRange]>; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index fb80dccc6fb9..80a4eaee1120 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -159,13 +159,13 @@ def err_typename_invalid_functionspec : Error< def err_invalid_decl_spec_combination : Error< "cannot combine with previous '%0' declaration specifier">; def err_invalid_vector_decl_spec_combination : Error< - "cannot combine with previous '%0' declaration specifier. \"__vector\" must be first">; + "cannot combine with previous '%0' declaration specifier. '__vector' must be first">; def err_invalid_pixel_decl_spec_combination : Error< - "\"__pixel\" must be preceded by \"__vector\". '%0' declaration specifier not allowed here">; + "'__pixel' must be preceded by '__vector'. '%0' declaration specifier not allowed here">; def err_invalid_vector_double_decl_spec_combination : Error< - "cannot use \"double\" with \"__vector\"">; + "cannot use 'double' with '__vector'">; def warn_vector_long_decl_spec_combination : Warning< - "Use of \"long\" with \"__vector\" is deprecated">; + "Use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>; def err_friend_invalid_in_context : Error< "'friend' used outside of class">; def err_unknown_typename : Error< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index badd64c31b56..13ac9ece542b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -31,10 +31,10 @@ def ext_predef_outside_function : Warning< "predefined identifier is only valid inside function">; def warn_float_overflow : Warning< "magnitude of floating-point constant too large for type %0; maximum is %1">, - InGroup<BadLiteral>; + InGroup<LiteralRange>; def warn_float_underflow : Warning< "magnitude of floating-point constant too small for type %0; minimum is %1">, - InGroup<BadLiteral>; + InGroup<LiteralRange>; // C99 Designated Initializers def err_array_designator_negative : Error< @@ -141,7 +141,8 @@ def err_using_decl_conflict_reverse : Error< def note_using_decl : Note<"%select{|previous }0using declaration">; def warn_access_decl_deprecated : Warning< - "access declarations are deprecated; use using declarations instead">; + "access declarations are deprecated; use using declarations instead">, + InGroup<Deprecated>; def err_invalid_thread : Error< "'__thread' is only allowed on variable declarations">; @@ -1580,6 +1581,9 @@ def err_bitfield_width_exceeds_type_size : Error< "size of bit-field %0 exceeds size of its type (%1 bits)">; def err_anon_bitfield_width_exceeds_type_size : Error< "size of anonymous bit-field exceeds size of its type (%0 bits)">; +def warn_missing_braces : Warning< + "suggest braces around initialization of subobject">, + InGroup<DiagGroup<"missing-braces">>, DefaultIgnore; def err_redefinition_of_label : Error<"redefinition of label '%0'">; def err_undeclared_label_use : Error<"use of undeclared label '%0'">; @@ -1785,7 +1789,7 @@ def err_array_init_not_init_list : Error< "array initializer must be an initializer " "list%select{| or string literal}0">; def warn_deprecated_string_literal_conversion : Warning< - "conversion from string literal to %0 is deprecated">; + "conversion from string literal to %0 is deprecated">, InGroup<Deprecated>; def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">; def err_typecheck_sclass_fscope : Error< "illegal storage class on file-scoped variable">; @@ -2043,11 +2047,11 @@ def note_delete_member_function_declared_here : Note< "%0 declared here">; def err_decrement_bool : Error<"cannot decrement expression of type bool">; def warn_increment_bool : Warning< - "incrementing expression of type bool is deprecated">; -def err_catch_incomplete_ptr : Error< - "cannot catch pointer to incomplete type %0">; -def err_catch_incomplete_ref : Error< - "cannot catch reference to incomplete type %0">; + "incrementing expression of type bool is deprecated">, InGroup<Deprecated>; +def ext_catch_incomplete_ptr : ExtWarn< + "ISO C++ forbids catching a pointer to incomplete type %0">; +def ext_catch_incomplete_ref : ExtWarn< + "ISO C++ forbids catching a reference to incomplete type %0">; def err_catch_incomplete : Error<"cannot catch incomplete type %0">; def err_catch_rvalue_ref : Error<"cannot catch exceptions by rvalue reference">; def err_qualified_catch_declarator : Error< diff --git a/include/clang/Checker/PathSensitive/SVals.h b/include/clang/Checker/PathSensitive/SVals.h index 65a8a2c01df5..040db831b8c0 100644 --- a/include/clang/Checker/PathSensitive/SVals.h +++ b/include/clang/Checker/PathSensitive/SVals.h @@ -112,6 +112,9 @@ public: /// wraps a symbol, return that SymbolRef. Otherwise return a SymbolData* SymbolRef getAsLocSymbol() const; + /// Get the symbol in the SVal or its base region. + SymbolRef getLocSymbolInBase() const; + /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef. /// Otherwise return a SymbolRef where 'isValid()' returns false. SymbolRef getAsSymbol() const; diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 1be4118e5542..828e9b5bf605 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -439,11 +439,11 @@ public: /// \param OS - The output stream, which should be non-null. void addOutputFile(llvm::StringRef Path, llvm::raw_ostream *OS); - /// ClearOutputFiles - Clear the output file list, destroying the contained + /// clearOutputFiles - Clear the output file list, destroying the contained /// output streams. /// /// \param EraseFiles - If true, attempt to erase the files from disk. - void ClearOutputFiles(bool EraseFiles); + void clearOutputFiles(bool EraseFiles); /// } /// @name Construction Utility Methods diff --git a/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def index c750492a270e..e839a8c4c772 100644 --- a/include/clang/Frontend/DeclXML.def +++ b/include/clang/Frontend/DeclXML.def @@ -103,7 +103,7 @@ NODE_XML(FunctionDecl, "Function") //ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference ATTRIBUTE_XML(getNumParams(), "num_args") SUB_NODE_SEQUENCE_XML(ParmVarDecl) - //SUB_NODE_OPT_XML("Body") + SUB_NODE_FN_BODY_XML END_NODE_XML NODE_XML(CXXMethodDecl, "CXXMethodDecl") @@ -118,13 +118,9 @@ NODE_XML(CXXMethodDecl, "CXXMethodDecl") ATTRIBUTE_OPT_XML(isVirtual(), "virtual") ATTRIBUTE_XML(getNumParams(), "num_args") SUB_NODE_SEQUENCE_XML(ParmVarDecl) - //SUB_NODE_OPT_XML("Body") + SUB_NODE_FN_BODY_XML END_NODE_XML -//NODE_XML("Body") -// SUB_NODE_XML(Stmt) -//END_NODE_XML - NODE_XML(NamespaceDecl, "Namespace") ID_ATTRIBUTE_XML ATTRIBUTE_FILE_LOCATION_XML @@ -156,6 +152,16 @@ NODE_XML(RecordDecl, "Record") SUB_NODE_SEQUENCE_XML(FieldDecl) END_NODE_XML +NODE_XML(CXXRecordDecl, "CXXRecord") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + ATTRIBUTE_OPT_XML(isDefinition() == false, "forward") + ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates + SUB_NODE_SEQUENCE_XML(FieldDecl) +END_NODE_XML + NODE_XML(EnumDecl, "Enum") ID_ATTRIBUTE_XML ATTRIBUTE_FILE_LOCATION_XML @@ -248,3 +254,4 @@ END_NODE_XML #undef SUB_NODE_XML #undef SUB_NODE_SEQUENCE_XML #undef SUB_NODE_OPT_XML +#undef SUB_NODE_FN_BODY_XML diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index d4014b307516..e234e9838a12 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -408,7 +408,9 @@ namespace clang { /// \brief A SubstTemplateTypeParmType record. TYPE_SUBST_TEMPLATE_TYPE_PARM = 25, /// \brief An UnresolvedUsingType record. - TYPE_UNRESOLVED_USING = 26 + TYPE_UNRESOLVED_USING = 26, + /// \brief An InjectedClassNameType record. + TYPE_INJECTED_CLASS_NAME = 27 }; /// \brief The type IDs for special types constructed by semantic diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index db9c884662ab..532d8e4b46f3 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -43,7 +43,7 @@ class ScratchBuffer; class TargetInfo; class PPCallbacks; class DirectoryLookup; - + /// Preprocessor - This object engages in a tight little dance with the lexer to /// efficiently preprocess tokens. Lexers know only about tokens within a /// single source file, and don't know anything about preprocessor-level issues @@ -60,7 +60,7 @@ class Preprocessor { /// \brief External source of macros. ExternalPreprocessorSource *ExternalSource; - + /// PTH - An optional PTHManager object used for getting tokens from /// a token cache rather than lexing the original source file. llvm::OwningPtr<PTHManager> PTH; @@ -105,7 +105,7 @@ class Preprocessor { /// \brief Whether we have already loaded macros from the external source. mutable bool ReadMacrosFromExternalSource : 1; - + /// Identifiers - This is mapping/lookup information for all identifiers in /// the program, including program keywords. mutable IdentifierTable Identifiers; @@ -186,7 +186,7 @@ class Preprocessor { /// allocation. /// FIXME: why not use a singly linked list? std::vector<MacroInfo*> MICache; - + /// MacroArgCache - This is a "freelist" of MacroArg objects that can be /// reused for quick allocation. MacroArgs *MacroArgCache; @@ -257,11 +257,11 @@ public: void setExternalSource(ExternalPreprocessorSource *Source) { ExternalSource = Source; } - + ExternalPreprocessorSource *getExternalSource() const { return ExternalSource; } - + /// SetCommentRetentionState - Control whether or not the preprocessor retains /// comments in output. void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) { @@ -287,11 +287,11 @@ public: /// expansions going on at the time. PreprocessorLexer *getCurrentFileLexer() const; - /// getPPCallbacks/setPPCallbacks - Accessors for preprocessor callbacks. + /// getPPCallbacks/addPPCallbacks - Accessors for preprocessor callbacks. /// Note that this class takes ownership of any PPCallbacks object given to /// it. PPCallbacks *getPPCallbacks() const { return Callbacks; } - void setPPCallbacks(PPCallbacks *C) { + void addPPCallbacks(PPCallbacks *C) { if (Callbacks) C = new PPChainedCallbacks(C, Callbacks); Callbacks = C; @@ -313,7 +313,7 @@ public: MacroInfo*>::const_iterator macro_iterator; macro_iterator macro_begin(bool IncludeExternalMacros = true) const; macro_iterator macro_end(bool IncludeExternalMacros = true) const; - + const std::string &getPredefines() const { return Predefines; } /// setPredefines - Set the predefines for this Preprocessor. These /// predefines are automatically injected when parsing the main file. @@ -523,7 +523,7 @@ public: /// (1-based). /// /// \returns true if an error occurred, false otherwise. - bool SetCodeCompletionPoint(const FileEntry *File, + bool SetCodeCompletionPoint(const FileEntry *File, unsigned Line, unsigned Column); /// \brief Determine if this source location refers into the file diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index 4fe81a7eb5c2..f6f1eb936b7a 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -228,7 +228,8 @@ public: AttrList(0), ProtocolQualifiers(0), NumProtocolQualifiers(0), - ProtocolLocs(0) { + ProtocolLocs(0), + writtenBS() { } ~DeclSpec() { delete AttrList; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d8c1c8485824..26b10b58713e 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -78,21 +78,21 @@ ASTContext::~ASTContext() { // Increment in loop to prevent using deallocated memory. Deallocate(&*I++); } - } - for (llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator - I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end(); I != E; ) { - // Increment in loop to prevent using deallocated memory. - ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second); - delete R; - } + for (llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator + I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end(); I != E; ) { + // Increment in loop to prevent using deallocated memory. + if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second)) + R->Destroy(*this); + } - for (llvm::DenseMap<const ObjCContainerDecl*, - const ASTRecordLayout*>::iterator - I = ObjCLayouts.begin(), E = ObjCLayouts.end(); I != E; ) { - // Increment in loop to prevent using deallocated memory. - ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second); - delete R; + for (llvm::DenseMap<const ObjCContainerDecl*, + const ASTRecordLayout*>::iterator + I = ObjCLayouts.begin(), E = ObjCLayouts.end(); I != E; ) { + // Increment in loop to prevent using deallocated memory. + if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second)) + R->Destroy(*this); + } } // Destroy nested-name-specifiers. @@ -888,6 +888,10 @@ ASTContext::getTypeInfo(const Type *T) { case Type::QualifiedName: return getTypeInfo(cast<QualifiedNameType>(T)->getNamedType().getTypePtr()); + case Type::InjectedClassName: + return getTypeInfo(cast<InjectedClassNameType>(T) + ->getUnderlyingType().getTypePtr()); + case Type::TemplateSpecialization: assert(getCanonicalType(T) != T && "Cannot request the size of a dependent type"); @@ -1918,38 +1922,71 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray, return QualType(FTP, 0); } +#ifndef NDEBUG +static bool NeedsInjectedClassNameType(const RecordDecl *D) { + if (!isa<CXXRecordDecl>(D)) return false; + const CXXRecordDecl *RD = cast<CXXRecordDecl>(D); + if (isa<ClassTemplatePartialSpecializationDecl>(RD)) + return true; + if (RD->getDescribedClassTemplate() && + !isa<ClassTemplateSpecializationDecl>(RD)) + return true; + return false; +} +#endif + +/// getInjectedClassNameType - Return the unique reference to the +/// injected class name type for the specified templated declaration. +QualType ASTContext::getInjectedClassNameType(CXXRecordDecl *Decl, + QualType TST) { + assert(NeedsInjectedClassNameType(Decl)); + if (Decl->TypeForDecl) { + assert(isa<InjectedClassNameType>(Decl->TypeForDecl)); + } else if (CXXRecordDecl *PrevDecl + = cast_or_null<CXXRecordDecl>(Decl->getPreviousDeclaration())) { + assert(PrevDecl->TypeForDecl && "previous declaration has no type"); + Decl->TypeForDecl = PrevDecl->TypeForDecl; + assert(isa<InjectedClassNameType>(Decl->TypeForDecl)); + } else { + Decl->TypeForDecl = new (*this, TypeAlignment) + InjectedClassNameType(Decl, TST, TST->getCanonicalTypeInternal()); + Types.push_back(Decl->TypeForDecl); + } + return QualType(Decl->TypeForDecl, 0); +} + /// getTypeDeclType - Return the unique reference to the type for the /// specified type declaration. -QualType ASTContext::getTypeDeclType(const TypeDecl *Decl, - const TypeDecl* PrevDecl) { +QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) { assert(Decl && "Passed null for Decl param"); - if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); + assert(!Decl->TypeForDecl && "TypeForDecl present in slow case"); if (const TypedefDecl *Typedef = dyn_cast<TypedefDecl>(Decl)) return getTypedefType(Typedef); - else if (isa<TemplateTypeParmDecl>(Decl)) { - assert(false && "Template type parameter types are always available."); - } else if (const ObjCInterfaceDecl *ObjCInterface + + if (const ObjCInterfaceDecl *ObjCInterface = dyn_cast<ObjCInterfaceDecl>(Decl)) return getObjCInterfaceType(ObjCInterface); + assert(!isa<TemplateTypeParmDecl>(Decl) && + "Template type parameter types are always available."); + if (const RecordDecl *Record = dyn_cast<RecordDecl>(Decl)) { - if (PrevDecl) - Decl->TypeForDecl = PrevDecl->TypeForDecl; - else - Decl->TypeForDecl = new (*this, TypeAlignment) RecordType(Record); + assert(!Record->getPreviousDeclaration() && + "struct/union has previous declaration"); + assert(!NeedsInjectedClassNameType(Record)); + Decl->TypeForDecl = new (*this, TypeAlignment) RecordType(Record); } else if (const EnumDecl *Enum = dyn_cast<EnumDecl>(Decl)) { - if (PrevDecl) - Decl->TypeForDecl = PrevDecl->TypeForDecl; - else - Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Enum); + assert(!Enum->getPreviousDeclaration() && + "enum has previous declaration"); + Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Enum); } else if (const UnresolvedUsingTypenameDecl *Using = dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) { Decl->TypeForDecl = new (*this, TypeAlignment) UnresolvedUsingType(Using); } else - assert(false && "TypeDecl without a type?"); + llvm_unreachable("TypeDecl without a type?"); - if (!PrevDecl) Types.push_back(Decl->TypeForDecl); + Types.push_back(Decl->TypeForDecl); return QualType(Decl->TypeForDecl, 0); } @@ -2022,6 +2059,24 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, return QualType(TypeParm, 0); } +TypeSourceInfo * +ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo &Args, + QualType CanonType) { + QualType TST = getTemplateSpecializationType(Name, Args, CanonType); + + TypeSourceInfo *DI = CreateTypeSourceInfo(TST); + TemplateSpecializationTypeLoc TL + = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc()); + TL.setTemplateNameLoc(NameLoc); + TL.setLAngleLoc(Args.getLAngleLoc()); + TL.setRAngleLoc(Args.getRAngleLoc()); + for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) + TL.setArgLocInfo(i, Args[i].getLocInfo()); + return DI; +} + QualType ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgumentListInfo &Args, diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index 7402b7dda4ec..866b7f799f05 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -56,6 +56,12 @@ static bool ShouldAKA(ASTContext &Context, QualType QT, QT = cast<QualifiedNameType>(Ty)->desugar(); continue; } + + // ...or an injected class name... + if (isa<InjectedClassNameType>(Ty)) { + QT = cast<InjectedClassNameType>(Ty)->desugar(); + continue; + } // ...or a substituted template type parameter. if (isa<SubstTemplateTypeParmType>(Ty)) { diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 2bcf07e70040..d9c0d7b6bed4 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -610,6 +610,16 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, break; } + case Type::InjectedClassName: { + const InjectedClassNameType *Inj1 = cast<InjectedClassNameType>(T1); + const InjectedClassNameType *Inj2 = cast<InjectedClassNameType>(T2); + if (!IsStructurallyEquivalent(Context, + Inj1->getUnderlyingType(), + Inj2->getUnderlyingType())) + return false; + break; + } + case Type::Typename: { const TypenameType *Typename1 = cast<TypenameType>(T1); const TypenameType *Typename2 = cast<TypenameType>(T2); @@ -2244,12 +2254,14 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { if (ResultTy.isNull()) return 0; + TypeSourceInfo *ResultTInfo = Importer.Import(D->getResultTypeSourceInfo()); + ObjCMethodDecl *ToMethod = ObjCMethodDecl::Create(Importer.getToContext(), Loc, Importer.Import(D->getLocEnd()), Name.getObjCSelector(), - ResultTy, DC, + ResultTy, ResultTInfo, DC, D->isInstanceMethod(), D->isVariadic(), D->isSynthesized(), diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index e5bd9b7722c5..2f1a6af77aa9 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -4,8 +4,8 @@ add_clang_library(clangAST APValue.cpp ASTConsumer.cpp ASTContext.cpp - ASTImporter.cpp ASTDiagnostic.cpp + ASTImporter.cpp AttrImpl.cpp CXXInheritance.cpp Decl.cpp @@ -23,6 +23,7 @@ add_clang_library(clangAST InheritViz.cpp NestedNameSpecifier.cpp ParentMap.cpp + RecordLayout.cpp RecordLayoutBuilder.cpp Stmt.cpp StmtDumper.cpp diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 9db6ae1329e4..a9495343e887 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -574,11 +574,22 @@ DeclContext *DeclContext::getPrimaryContext() { if (DeclKind >= Decl::TagFirst && DeclKind <= Decl::TagLast) { // If this is a tag type that has a definition or is currently // being defined, that definition is our primary context. - if (const TagType *TagT =cast<TagDecl>(this)->TypeForDecl->getAs<TagType>()) - if (TagT->isBeingDefined() || - (TagT->getDecl() && TagT->getDecl()->isDefinition())) - return TagT->getDecl(); - return this; + TagDecl *Tag = cast<TagDecl>(this); + assert(isa<TagType>(Tag->TypeForDecl) || + isa<InjectedClassNameType>(Tag->TypeForDecl)); + + if (TagDecl *Def = Tag->getDefinition()) + return Def; + + if (!isa<InjectedClassNameType>(Tag->TypeForDecl)) { + const TagType *TagTy = cast<TagType>(Tag->TypeForDecl); + if (TagTy->isBeingDefined()) + // FIXME: is it necessarily being defined in the decl + // that owns the type? + return TagTy->getDecl(); + } + + return Tag; } assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast && diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 9b693af5bc92..7f4ad34fb7f8 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -636,11 +636,16 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const { assert(isInstance() && "No 'this' for static methods!"); - QualType ClassTy; - if (ClassTemplateDecl *TD = getParent()->getDescribedClassTemplate()) - ClassTy = TD->getInjectedClassNameType(C); - else - ClassTy = C.getTagDeclType(getParent()); + QualType ClassTy = C.getTypeDeclType(getParent()); + + // Aesthetically we prefer not to synthesize a type as the + // InjectedClassNameType of a template pattern: injected class names + // are printed without template arguments, which might + // surprise/confuse/distract our poor users if they didn't + // explicitly write one. + if (isa<InjectedClassNameType>(ClassTy)) + ClassTy = cast<InjectedClassNameType>(ClassTy)->getUnderlyingType(); + ClassTy = C.getQualifiedType(ClassTy, Qualifiers::fromCVRMask(getTypeQualifiers())); return C.getPointerType(ClassTy); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 8decafa35e34..67b71a0c44e5 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -304,15 +304,16 @@ ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, QualType T, + TypeSourceInfo *ResultTInfo, DeclContext *contextDecl, bool isInstance, bool isVariadic, bool isSynthesized, ImplementationControl impControl) { return new (C) ObjCMethodDecl(beginLoc, endLoc, - SelInfo, T, contextDecl, - isInstance, - isVariadic, isSynthesized, impControl); + SelInfo, T, ResultTInfo, contextDecl, + isInstance, + isVariadic, isSynthesized, impControl); } void ObjCMethodDecl::Destroy(ASTContext &C) { diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index d80db45f4557..b44939862445 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -193,7 +193,8 @@ ClassTemplateDecl::findPartialSpecialization(QualType T) { return 0; } -QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) { +QualType +ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) { if (!CommonPtr->InjectedClassNameType.isNull()) return CommonPtr->InjectedClassNameType; @@ -393,6 +394,7 @@ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, SpecializedTemplate->getIdentifier(), PrevDecl), SpecializedTemplate(SpecializedTemplate), + TypeAsWritten(0), TemplateArgs(Context, Builder, /*TakeArgs=*/true), SpecializationKind(TSK_Undeclared) { } @@ -453,6 +455,7 @@ Create(ASTContext &Context, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, const TemplateArgumentListInfo &ArgInfos, + QualType CanonInjectedType, ClassTemplatePartialSpecializationDecl *PrevDecl) { unsigned N = ArgInfos.size(); TemplateArgumentLoc *ClonedArgs = new (Context) TemplateArgumentLoc[N]; @@ -467,7 +470,8 @@ Create(ASTContext &Context, DeclContext *DC, SourceLocation L, ClonedArgs, N, PrevDecl); Result->setSpecializationKind(TSK_ExplicitSpecialization); - Context.getTypeDeclType(Result, PrevDecl); + + Context.getInjectedClassNameType(Result, CanonInjectedType); return Result; } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index a2914bc6bf4e..efd0fd1b8dcb 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -181,7 +181,6 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { } PrintingPolicy Policy(Context.getLangOptions()); - Policy.SuppressTagKind = true; std::string Proto = FD->getQualifiedNameAsString(Policy); @@ -2115,12 +2114,12 @@ ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, Expr *receiver, // constructor for class messages. // FIXME: clsName should be typed to ObjCInterfaceType ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName, - Selector selInfo, QualType retType, - ObjCMethodDecl *mproto, + SourceLocation clsNameLoc, Selector selInfo, + QualType retType, ObjCMethodDecl *mproto, SourceLocation LBrac, SourceLocation RBrac, Expr **ArgExprs, unsigned nargs) - : Expr(ObjCMessageExprClass, retType, false, false), SelName(selInfo), - MethodProto(mproto) { + : Expr(ObjCMessageExprClass, retType, false, false), ClassNameLoc(clsNameLoc), + SelName(selInfo), MethodProto(mproto) { NumArgs = nargs; SubExprs = new (C) Stmt*[NumArgs+1]; SubExprs[RECEIVER] = (Expr*) ((uintptr_t) clsName | IsClsMethDeclUnknown); @@ -2134,12 +2133,14 @@ ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName, // constructor for class messages. ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, ObjCInterfaceDecl *cls, - Selector selInfo, QualType retType, + SourceLocation clsNameLoc, Selector selInfo, + QualType retType, ObjCMethodDecl *mproto, SourceLocation LBrac, SourceLocation RBrac, Expr **ArgExprs, unsigned nargs) -: Expr(ObjCMessageExprClass, retType, false, false), SelName(selInfo), -MethodProto(mproto) { + : Expr(ObjCMessageExprClass, retType, false, false), ClassNameLoc(clsNameLoc), + SelName(selInfo), MethodProto(mproto) +{ NumArgs = nargs; SubExprs = new (C) Stmt*[NumArgs+1]; SubExprs[RECEIVER] = (Expr*) ((uintptr_t) cls | IsClsMethDeclKnown); @@ -2157,23 +2158,27 @@ ObjCMessageExpr::ClassInfo ObjCMessageExpr::getClassInfo() const { default: assert(false && "Invalid ObjCMessageExpr."); case IsInstMeth: - return ClassInfo(0, 0); + return ClassInfo(0, 0, SourceLocation()); case IsClsMethDeclUnknown: - return ClassInfo(0, (IdentifierInfo*) (x & ~Flags)); + return ClassInfo(0, (IdentifierInfo*) (x & ~Flags), ClassNameLoc); case IsClsMethDeclKnown: { ObjCInterfaceDecl* D = (ObjCInterfaceDecl*) (x & ~Flags); - return ClassInfo(D, D->getIdentifier()); + return ClassInfo(D, D->getIdentifier(), ClassNameLoc); } } } void ObjCMessageExpr::setClassInfo(const ObjCMessageExpr::ClassInfo &CI) { - if (CI.first == 0 && CI.second == 0) + if (CI.Decl == 0 && CI.Name == 0) { SubExprs[RECEIVER] = (Expr*)((uintptr_t)0 | IsInstMeth); - else if (CI.first == 0) - SubExprs[RECEIVER] = (Expr*)((uintptr_t)CI.second | IsClsMethDeclUnknown); + return; + } + + if (CI.Decl == 0) + SubExprs[RECEIVER] = (Expr*)((uintptr_t)CI.Name | IsClsMethDeclUnknown); else - SubExprs[RECEIVER] = (Expr*)((uintptr_t)CI.first | IsClsMethDeclKnown); + SubExprs[RECEIVER] = (Expr*)((uintptr_t)CI.Decl | IsClsMethDeclKnown); + ClassNameLoc = CI.Loc; } void ObjCMessageExpr::DoDestroy(ASTContext &C) { diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index e26c0bba4934..45518e98bc15 100644 --- a/lib/AST/NestedNameSpecifier.cpp +++ b/lib/AST/NestedNameSpecifier.cpp @@ -142,7 +142,6 @@ NestedNameSpecifier::print(llvm::raw_ostream &OS, Type *T = getAsType(); PrintingPolicy InnerPolicy(Policy); - InnerPolicy.SuppressTagKind = true; InnerPolicy.SuppressScope = true; // Nested-name-specifiers are intended to contain minimally-qualified diff --git a/lib/AST/RecordLayout.cpp b/lib/AST/RecordLayout.cpp new file mode 100644 index 000000000000..838753a1433f --- /dev/null +++ b/lib/AST/RecordLayout.cpp @@ -0,0 +1,67 @@ +//===-- RecordLayout.cpp - Layout information for a struct/union -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the RecordLayout interface. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" + +using namespace clang; + +void ASTRecordLayout::Destroy(ASTContext &Ctx) { + if (FieldOffsets) + Ctx.Deallocate(FieldOffsets); + if (CXXInfo) + Ctx.Deallocate(CXXInfo); + this->~ASTRecordLayout(); + Ctx.Deallocate(this); +} + +ASTRecordLayout::ASTRecordLayout(ASTContext &Ctx, uint64_t size, unsigned alignment, + unsigned datasize, const uint64_t *fieldoffsets, + unsigned fieldcount) + : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment), + FieldCount(fieldcount), CXXInfo(0) { + if (FieldCount > 0) { + FieldOffsets = new (Ctx) uint64_t[FieldCount]; + memcpy(FieldOffsets, fieldoffsets, FieldCount * sizeof(*FieldOffsets)); + } +} + +// Constructor for C++ records. +ASTRecordLayout::ASTRecordLayout(ASTContext &Ctx, + uint64_t size, unsigned alignment, + uint64_t datasize, + const uint64_t *fieldoffsets, + unsigned fieldcount, + uint64_t nonvirtualsize, + unsigned nonvirtualalign, + const PrimaryBaseInfo &PrimaryBase, + const std::pair<const CXXRecordDecl *, uint64_t> *bases, + unsigned numbases, + const std::pair<const CXXRecordDecl *, uint64_t> *vbases, + unsigned numvbases) + : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment), + FieldCount(fieldcount), CXXInfo(new (Ctx) CXXRecordLayoutInfo) +{ + if (FieldCount > 0) { + FieldOffsets = new (Ctx) uint64_t[FieldCount]; + memcpy(FieldOffsets, fieldoffsets, FieldCount * sizeof(*FieldOffsets)); + } + + CXXInfo->PrimaryBase = PrimaryBase; + CXXInfo->NonVirtualSize = nonvirtualsize; + CXXInfo->NonVirtualAlign = nonvirtualalign; + for (unsigned i = 0; i != numbases; ++i) + CXXInfo->BaseOffsets[bases[i].first] = bases[i].second; + for (unsigned i = 0; i != numvbases; ++i) + CXXInfo->VBaseOffsets[vbases[i].first] = vbases[i].second; +} diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 10c5089f2253..22285ca42032 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -675,9 +675,10 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, Builder.Layout(D); if (!isa<CXXRecordDecl>(D)) - return new ASTRecordLayout(Builder.Size, Builder.Alignment, Builder.Size, - Builder.FieldOffsets.data(), - Builder.FieldOffsets.size()); + return new (Ctx) ASTRecordLayout(Ctx, Builder.Size, Builder.Alignment, + Builder.Size, + Builder.FieldOffsets.data(), + Builder.FieldOffsets.size()); // FIXME: This is not always correct. See the part about bitfields at // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info. @@ -690,16 +691,16 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, uint64_t NonVirtualSize = IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize; - return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize, - Builder.FieldOffsets.data(), - Builder.FieldOffsets.size(), - NonVirtualSize, - Builder.NonVirtualAlignment, - Builder.PrimaryBase, - Builder.Bases.data(), - Builder.Bases.size(), - Builder.VBases.data(), - Builder.VBases.size()); + return new (Ctx) ASTRecordLayout(Ctx, Builder.Size, Builder.Alignment, + DataSize, Builder.FieldOffsets.data(), + Builder.FieldOffsets.size(), + NonVirtualSize, + Builder.NonVirtualAlignment, + Builder.PrimaryBase, + Builder.Bases.data(), + Builder.Bases.size(), + Builder.VBases.data(), + Builder.VBases.size()); } const ASTRecordLayout * @@ -710,10 +711,10 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, Builder.Layout(D, Impl); - return new ASTRecordLayout(Builder.Size, Builder.Alignment, - Builder.DataSize, - Builder.FieldOffsets.data(), - Builder.FieldOffsets.size()); + return new (Ctx) ASTRecordLayout(Ctx, Builder.Size, Builder.Alignment, + Builder.DataSize, + Builder.FieldOffsets.data(), + Builder.FieldOffsets.size()); } const CXXMethodDecl * diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 76cc38292064..8a64f8ea97ec 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -650,6 +650,7 @@ bool Type::isPODType() const { case Vector: case ExtVector: case ObjCObjectPointer: + case BlockPointer: return true; case Enum: diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 5b621cf7280d..037bc14e7a91 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -30,7 +30,8 @@ namespace { explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { } void Print(QualType T, std::string &S); - void PrintTag(const TagType *T, std::string &S); + void AppendScope(DeclContext *DC, std::string &S); + void PrintTag(TagDecl *T, std::string &S); #define ABSTRACT_TYPE(CLASS, PARENT) #define TYPE(CLASS, PARENT) \ void Print##CLASS(const CLASS##Type *T, std::string &S); @@ -330,19 +331,21 @@ void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T, Print(T->getResultType(), S); } -void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T, - std::string &S) { - IdentifierInfo *II = T->getDecl()->getIdentifier(); +static void PrintTypeSpec(const NamedDecl *D, std::string &S) { + IdentifierInfo *II = D->getIdentifier(); if (S.empty()) S = II->getName().str(); else S = II->getName().str() + ' ' + S; } +void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T, + std::string &S) { + PrintTypeSpec(T->getDecl(), S); +} + void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) { - if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. - S = ' ' + S; - S = T->getDecl()->getIdentifier()->getName().str() + S; + PrintTypeSpec(T->getDecl(), S); } void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) { @@ -371,89 +374,106 @@ void TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) { S = "decltype(" + s.str() + ")" + S; } -void TypePrinter::PrintTag(const TagType *T, std::string &InnerString) { +/// Appends the given scope to the end of a string. +void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) { + if (DC->isTranslationUnit()) return; + AppendScope(DC->getParent(), Buffer); + + unsigned OldSize = Buffer.size(); + + if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) { + if (NS->getIdentifier()) + Buffer += NS->getNameAsString(); + else + Buffer += "<anonymous>"; + } else if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { + const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); + std::string TemplateArgsStr + = TemplateSpecializationType::PrintTemplateArgumentList( + TemplateArgs.getFlatArgumentList(), + TemplateArgs.flat_size(), + Policy); + Buffer += Spec->getIdentifier()->getName(); + Buffer += TemplateArgsStr; + } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { + if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl()) + Buffer += Typedef->getIdentifier()->getName(); + else if (Tag->getIdentifier()) + Buffer += Tag->getIdentifier()->getName(); + } + + if (Buffer.size() != OldSize) + Buffer += "::"; +} + +void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) { if (Policy.SuppressTag) return; - - if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'. - InnerString = ' ' + InnerString; - - const char *Kind = Policy.SuppressTagKind? 0 : T->getDecl()->getKindName(); + + std::string Buffer; + + // We don't print tags unless this is an elaborated type. + // In C, we just assume every RecordType is an elaborated type. + if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) { + Buffer += D->getKindName(); + Buffer += ' '; + } + + if (!Policy.SuppressScope) + // Compute the full nested-name-specifier for this type. In C, + // this will always be empty. + AppendScope(D->getDeclContext(), Buffer); + const char *ID; - if (const IdentifierInfo *II = T->getDecl()->getIdentifier()) + if (const IdentifierInfo *II = D->getIdentifier()) ID = II->getNameStart(); - else if (TypedefDecl *Typedef = T->getDecl()->getTypedefForAnonDecl()) { - Kind = 0; + else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) { assert(Typedef->getIdentifier() && "Typedef without identifier?"); ID = Typedef->getIdentifier()->getNameStart(); } else ID = "<anonymous>"; - + Buffer += ID; + // If this is a class template specialization, print the template // arguments. if (ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) { - const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - std::string TemplateArgsStr - = TemplateSpecializationType::PrintTemplateArgumentList( - TemplateArgs.getFlatArgumentList(), - TemplateArgs.flat_size(), - Policy); - InnerString = TemplateArgsStr + InnerString; - } - - if (!Policy.SuppressScope) { - // Compute the full nested-name-specifier for this type. In C, - // this will always be empty. - std::string ContextStr; - for (DeclContext *DC = T->getDecl()->getDeclContext(); - !DC->isTranslationUnit(); DC = DC->getParent()) { - std::string MyPart; - if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) { - if (NS->getIdentifier()) - MyPart = NS->getNameAsString(); - } else if (ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { - const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - std::string TemplateArgsStr - = TemplateSpecializationType::PrintTemplateArgumentList( - TemplateArgs.getFlatArgumentList(), - TemplateArgs.flat_size(), - Policy); - MyPart = Spec->getIdentifier()->getName().str() + TemplateArgsStr; - } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { - if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl()) - MyPart = Typedef->getIdentifier()->getName(); - else if (Tag->getIdentifier()) - MyPart = Tag->getIdentifier()->getName(); - } - - if (!MyPart.empty()) - ContextStr = MyPart + "::" + ContextStr; + = dyn_cast<ClassTemplateSpecializationDecl>(D)) { + const TemplateArgument *Args; + unsigned NumArgs; + if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) { + const TemplateSpecializationType *TST = + cast<TemplateSpecializationType>(TAW->getType()); + Args = TST->getArgs(); + NumArgs = TST->getNumArgs(); + } else { + const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); + Args = TemplateArgs.getFlatArgumentList(); + NumArgs = TemplateArgs.flat_size(); } - - if (Kind) - InnerString = std::string(Kind) + ' ' + ContextStr + ID + InnerString; - else - InnerString = ContextStr + ID + InnerString; - } else - InnerString = ID + InnerString; + Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args, + NumArgs, + Policy); + } + + if (!InnerString.empty()) { + Buffer += ' '; + Buffer += InnerString; + } + + std::swap(Buffer, InnerString); } void TypePrinter::PrintRecord(const RecordType *T, std::string &S) { - PrintTag(T, S); + PrintTag(T->getDecl(), S); } void TypePrinter::PrintEnum(const EnumType *T, std::string &S) { - PrintTag(T, S); + PrintTag(T->getDecl(), S); } void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) { - std::string TypeStr; - PrintingPolicy InnerPolicy(Policy); - InnerPolicy.SuppressTagKind = true; - TypePrinter(InnerPolicy).Print(T->getUnderlyingType(), S); - + Print(T->getUnderlyingType(), S); S = std::string(T->getNameForTagKind(T->getTagKind())) + ' ' + S; } @@ -494,6 +514,11 @@ void TypePrinter::PrintTemplateSpecialization( S = SpecString + ' ' + S; } +void TypePrinter::PrintInjectedClassName(const InjectedClassNameType *T, + std::string &S) { + PrintTemplateSpecialization(T->getUnderlyingTST(), S); +} + void TypePrinter::PrintQualifiedName(const QualifiedNameType *T, std::string &S) { std::string MyString; @@ -505,7 +530,6 @@ void TypePrinter::PrintQualifiedName(const QualifiedNameType *T, std::string TypeStr; PrintingPolicy InnerPolicy(Policy); - InnerPolicy.SuppressTagKind = true; InnerPolicy.SuppressScope = true; TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr); diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp index d9933e85cb91..5640c4a461e0 100644 --- a/lib/Analysis/AnalysisContext.cpp +++ b/lib/Analysis/AnalysisContext.cpp @@ -12,15 +12,16 @@ // //===----------------------------------------------------------------------===// -#include "clang/Analysis/CFG.h" -#include "clang/Analysis/AnalysisContext.h" -#include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ParentMap.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Analysis/Analyses/LiveVariables.h" +#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/CFG.h" #include "clang/Analysis/Support/BumpVector.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -207,11 +208,17 @@ class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{ BumpVector<const VarDecl*> &BEVals; BumpVectorContext &BC; llvm::DenseMap<const VarDecl*, unsigned> Visited; + llvm::SmallSet<const DeclContext*, 4> IgnoredContexts; public: FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals, BumpVectorContext &bc) : BEVals(bevals), BC(bc) {} - + + bool IsTrackedDecl(const VarDecl *VD) { + const DeclContext *DC = VD->getDeclContext(); + return IgnoredContexts.count(DC) == 0; + } + void VisitStmt(Stmt *S) { for (Stmt::child_iterator I = S->child_begin(), E = S->child_end();I!=E;++I) if (Stmt *child = *I) @@ -229,16 +236,23 @@ public: } } } - + void VisitBlockDeclRefExpr(BlockDeclRefExpr *DR) { if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { unsigned &flag = Visited[VD]; if (!flag) { flag = 1; - BEVals.push_back(VD, BC); + if (IsTrackedDecl(VD)) + BEVals.push_back(VD, BC); } } } + + void VisitBlockExpr(BlockExpr *BR) { + // Blocks containing blocks can transitively capture more variables. + IgnoredContexts.insert(BR->getBlockDecl()); + Visit(BR->getBlockDecl()->getBody()); + } }; } // end anonymous namespace diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index ae6d5df673c0..3b226d0cdc52 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -598,6 +598,134 @@ public: } // end anonymous namespace. namespace { +// MBlaze abstract base class +class MBlazeTargetInfo : public TargetInfo { + static const char * const GCCRegNames[]; + static const TargetInfo::GCCRegAlias GCCRegAliases[]; + +public: + MBlazeTargetInfo(const std::string& triple) : TargetInfo(triple) { + DescriptionString = "E-p:32:32-i8:8:8-i16:16:16-i64:32:32-f64:32:32-" + "v64:32:32-v128:32:32-n32"; + } + + virtual void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const { + // FIXME: Implement. + Records = 0; + NumRecords = 0; + } + + virtual void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const; + + virtual const char *getVAListDeclaration() const { + return "typedef char* __builtin_va_list;"; + } + virtual const char *getTargetPrefix() const { + return "mblaze"; + } + virtual void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const; + virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const; + virtual bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const { + switch (*Name) { + default: return false; + case 'O': // Zero + return true; + case 'b': // Base register + case 'f': // Floating point register + Info.setAllowsRegister(); + return true; + } + } + virtual const char *getClobbers() const { + return ""; + } +}; + +/// MBlazeTargetInfo::getTargetDefines - Return a set of the MBlaze-specific +/// #defines that are not tied to a specific subtarget. +void MBlazeTargetInfo::getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + // Target identification. + Builder.defineMacro("__microblaze__"); + Builder.defineMacro("_ARCH_MICROBLAZE"); + Builder.defineMacro("__MICROBLAZE__"); + + // Target properties. + Builder.defineMacro("_BIG_ENDIAN"); + Builder.defineMacro("__BIG_ENDIAN__"); + + // Subtarget options. + Builder.defineMacro("__REGISTER_PREFIX__", ""); +} + + +const char * const MBlazeTargetInfo::GCCRegNames[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", + "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", + "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", + "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", + "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", + "hi", "lo", "accum","rmsr", "$fcc1","$fcc2","$fcc3","$fcc4", + "$fcc5","$fcc6","$fcc7","$ap", "$rap", "$frp" +}; + +void MBlazeTargetInfo::getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const { + Names = GCCRegNames; + NumNames = llvm::array_lengthof(GCCRegNames); +} + +const TargetInfo::GCCRegAlias MBlazeTargetInfo::GCCRegAliases[] = { + { {"f0"}, "r0" }, + { {"f1"}, "r1" }, + { {"f2"}, "r2" }, + { {"f3"}, "r3" }, + { {"f4"}, "r4" }, + { {"f5"}, "r5" }, + { {"f6"}, "r6" }, + { {"f7"}, "r7" }, + { {"f8"}, "r8" }, + { {"f9"}, "r9" }, + { {"f10"}, "r10" }, + { {"f11"}, "r11" }, + { {"f12"}, "r12" }, + { {"f13"}, "r13" }, + { {"f14"}, "r14" }, + { {"f15"}, "r15" }, + { {"f16"}, "r16" }, + { {"f17"}, "r17" }, + { {"f18"}, "r18" }, + { {"f19"}, "r19" }, + { {"f20"}, "r20" }, + { {"f21"}, "r21" }, + { {"f22"}, "r22" }, + { {"f23"}, "r23" }, + { {"f24"}, "r24" }, + { {"f25"}, "r25" }, + { {"f26"}, "r26" }, + { {"f27"}, "r27" }, + { {"f28"}, "r28" }, + { {"f29"}, "r29" }, + { {"f30"}, "r30" }, + { {"f31"}, "r31" }, +}; + +void MBlazeTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const { + Aliases = GCCRegAliases; + NumAliases = llvm::array_lengthof(GCCRegAliases); +} +} // end anonymous namespace. + +namespace { // Namespace for x86 abstract base class const Builtin::Info BuiltinInfo[] = { #define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false }, @@ -2159,6 +2287,9 @@ static TargetInfo *AllocateTarget(const std::string &T) { return new FreeBSDTargetInfo<PPC64TargetInfo>(T); return new PPC64TargetInfo(T); + case llvm::Triple::mblaze: + return new MBlazeTargetInfo(T); + case llvm::Triple::sparc: if (os == llvm::Triple::AuroraUX) return new AuroraUXSparcV8TargetInfo(T); diff --git a/lib/Checker/BasicStore.cpp b/lib/Checker/BasicStore.cpp index d93a6658c681..10136f3fc45b 100644 --- a/lib/Checker/BasicStore.cpp +++ b/lib/Checker/BasicStore.cpp @@ -142,7 +142,8 @@ SVal BasicStoreManager::LazyRetrieve(Store store, const TypedRegion *R) { // Globals and parameters start with symbolic values. // Local variables initially are undefined. - if (VR->hasGlobalsOrParametersStorage()) + if (VR->hasGlobalsOrParametersStorage() || + isa<UnknownSpaceRegion>(VR->getMemorySpace())) return ValMgr.getRegionValueSymbolVal(R); return UndefinedVal(); } diff --git a/lib/Checker/CFRefCount.cpp b/lib/Checker/CFRefCount.cpp index ecb98a0496f0..9a76f6a2a3ad 100644 --- a/lib/Checker/CFRefCount.cpp +++ b/lib/Checker/CFRefCount.cpp @@ -853,7 +853,7 @@ public: RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME) { return getClassMethodSummary(ME->getSelector(), ME->getClassName(), - ME->getClassInfo().first, + ME->getClassInfo().Decl, ME->getMethodDecl(), ME->getType()); } @@ -2511,7 +2511,7 @@ static QualType GetReturnType(const Expr* RetE, ASTContext& Ctx) { // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this // is a call to a class method whose type we can resolve. In such // cases, promote the return type to XXX* (where XXX is the class). - const ObjCInterfaceDecl *D = ME->getClassInfo().first; + const ObjCInterfaceDecl *D = ME->getClassInfo().Decl; return !D ? RetTy : Ctx.getPointerType(Ctx.getObjCInterfaceType(D)); } diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index 2ea689e56a82..130d805bb8aa 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -25,7 +25,6 @@ #include "clang/Basic/PrettyStackTrace.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/ImmutableList.h" -#include "llvm/ADT/StringSwitch.h" #ifndef NDEBUG #include "llvm/Support/GraphWriter.h" diff --git a/lib/Checker/MallocChecker.cpp b/lib/Checker/MallocChecker.cpp index 4ff98642e1c2..a08afc4b7959 100644 --- a/lib/Checker/MallocChecker.cpp +++ b/lib/Checker/MallocChecker.cpp @@ -57,17 +57,20 @@ class RegionState {}; class MallocChecker : public CheckerVisitor<MallocChecker> { BuiltinBug *BT_DoubleFree; BuiltinBug *BT_Leak; + BuiltinBug *BT_UseFree; IdentifierInfo *II_malloc, *II_free, *II_realloc; public: MallocChecker() - : BT_DoubleFree(0), BT_Leak(0), II_malloc(0), II_free(0), II_realloc(0) {} + : BT_DoubleFree(0), BT_Leak(0), BT_UseFree(0), + II_malloc(0), II_free(0), II_realloc(0) {} static void *getTag(); bool EvalCallExpr(CheckerContext &C, const CallExpr *CE); void EvalDeadSymbols(CheckerContext &C,const Stmt *S,SymbolReaper &SymReaper); void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng); void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S); const GRState *EvalAssume(const GRState *state, SVal Cond, bool Assumption); + void VisitLocation(CheckerContext &C, const Stmt *S, SVal l); private: void MallocMem(CheckerContext &C, const CallExpr *CE); @@ -339,3 +342,22 @@ const GRState *MallocChecker::EvalAssume(const GRState *state, SVal Cond, return state; } + +// Check if the location is a freed symbolic region. +void MallocChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l) { + SymbolRef Sym = l.getLocSymbolInBase(); + if (Sym) { + const RefState *RS = C.getState()->get<RegionState>(Sym); + if (RS) + if (RS->isReleased()) { + ExplodedNode *N = C.GenerateSink(); + if (!BT_UseFree) + BT_UseFree = new BuiltinBug("Use dynamically allocated memory after" + " it is freed."); + + BugReport *R = new BugReport(*BT_UseFree, BT_UseFree->getDescription(), + N); + C.EmitReport(R); + } + } +} diff --git a/lib/Checker/RegionStore.cpp b/lib/Checker/RegionStore.cpp index fd48f72dd4ae..91c3a15f4473 100644 --- a/lib/Checker/RegionStore.cpp +++ b/lib/Checker/RegionStore.cpp @@ -41,25 +41,25 @@ public: enum Kind { Direct = 0x0, Default = 0x1 }; private: llvm ::PointerIntPair<const MemRegion*, 1> P; - uint64_t Offset; - + uint64_t Offset; + explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k) : P(r, (unsigned) k), Offset(offset) { assert(r); } public: - + bool isDefault() const { return P.getInt() == Default; } bool isDirect() const { return P.getInt() == Direct; } - + const MemRegion *getRegion() const { return P.getPointer(); } uint64_t getOffset() const { return Offset; } - + void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddPointer(P.getOpaqueValue()); ID.AddInteger(Offset); } - + static BindingKey Make(const MemRegion *R, Kind k); - + bool operator<(const BindingKey &X) const { if (P.getOpaqueValue() < X.P.getOpaqueValue()) return true; @@ -67,16 +67,16 @@ public: return false; return Offset < X.Offset; } - + bool operator==(const BindingKey &X) const { return P.getOpaqueValue() == X.P.getOpaqueValue() && Offset == X.Offset; } -}; +}; } // end anonymous namespace namespace llvm { - static inline + static inline llvm::raw_ostream& operator<<(llvm::raw_ostream& os, BindingKey K) { os << '(' << K.getRegion() << ',' << K.getOffset() << ',' << (K.isDirect() ? "direct" : "default") @@ -174,7 +174,7 @@ public: void process(llvm::SmallVectorImpl<const SubRegion*> &WL, const SubRegion *R); ~RegionStoreSubRegionMap() {} - + const Set *getSubRegions(const MemRegion *Parent) const { Map::const_iterator I = M.find(Parent); return I == M.end() ? NULL : &I->second; @@ -196,13 +196,10 @@ public: } }; - + class RegionStoreManager : public StoreManager { const RegionStoreFeatures Features; RegionBindings::Factory RBFactory; - - typedef llvm::DenseMap<Store, RegionStoreSubRegionMap*> SMCache; - SMCache SC; public: RegionStoreManager(GRStateManager& mgr, const RegionStoreFeatures &f) @@ -210,11 +207,6 @@ public: Features(f), RBFactory(mgr.getAllocator()) {} - virtual ~RegionStoreManager() { - for (SMCache::iterator I = SC.begin(), E = SC.end(); I != E; ++I) - delete (*I).second; - } - SubRegionMap *getSubRegionMap(Store store) { return getRegionStoreSubRegionMap(store); } @@ -226,10 +218,10 @@ public: /// getDefaultBinding - Returns an SVal* representing an optional default /// binding associated with a region and its subregions. Optional<SVal> getDefaultBinding(RegionBindings B, const MemRegion *R); - + /// setImplicitDefaultValue - Set the default binding for the provided /// MemRegion to the value implicitly defined for compound literals when - /// the value is not specified. + /// the value is not specified. Store setImplicitDefaultValue(Store store, const MemRegion *R, QualType T); /// ArrayToPointer - Emulates the "decay" of an array to a pointer @@ -250,11 +242,11 @@ public: // Binding values to regions. //===-------------------------------------------------------------------===// - Store InvalidateRegion(Store store, const MemRegion *R, const Expr *E, + Store InvalidateRegion(Store store, const MemRegion *R, const Expr *E, unsigned Count, InvalidatedSymbols *IS) { return RegionStoreManager::InvalidateRegions(store, &R, &R+1, E, Count, IS); } - + Store InvalidateRegions(Store store, const MemRegion * const *Begin, const MemRegion * const *End, @@ -262,7 +254,7 @@ public: InvalidatedSymbols *IS); public: // Made public for helper classes. - + void RemoveSubRegionBindings(RegionBindings &B, const MemRegion *R, RegionStoreSubRegionMap &M); @@ -270,17 +262,17 @@ public: // Made public for helper classes. RegionBindings Add(RegionBindings B, const MemRegion *R, BindingKey::Kind k, SVal V); - + const SVal *Lookup(RegionBindings B, BindingKey K); const SVal *Lookup(RegionBindings B, const MemRegion *R, BindingKey::Kind k); RegionBindings Remove(RegionBindings B, BindingKey K); RegionBindings Remove(RegionBindings B, const MemRegion *R, BindingKey::Kind k); - + RegionBindings Remove(RegionBindings B, const MemRegion *R) { return Remove(Remove(B, R, BindingKey::Direct), R, BindingKey::Default); - } + } Store Remove(Store store, BindingKey K); @@ -306,7 +298,7 @@ public: // Part of public interface to class. Store KillStruct(Store store, const TypedRegion* R); Store Remove(Store store, Loc LV); - + //===------------------------------------------------------------------===// // Loading values from regions. @@ -373,7 +365,7 @@ public: // Part of public interface to class. //===------------------------------------------------------------------===// const GRState *setExtent(const GRState *state,const MemRegion* R,SVal Extent); - DefinedOrUnknownSVal getSizeInElements(const GRState *state, + DefinedOrUnknownSVal getSizeInElements(const GRState *state, const MemRegion* R, QualType EleTy); //===------------------------------------------------------------------===// @@ -449,85 +441,148 @@ RegionStoreManager::getRegionStoreSubRegionMap(Store store) { } //===----------------------------------------------------------------------===// -// Binding invalidation. +// Region Cluster analysis. //===----------------------------------------------------------------------===// -void RegionStoreManager::RemoveSubRegionBindings(RegionBindings &B, - const MemRegion *R, - RegionStoreSubRegionMap &M) { - - if (const RegionStoreSubRegionMap::Set *S = M.getSubRegions(R)) - for (RegionStoreSubRegionMap::Set::iterator I = S->begin(), E = S->end(); - I != E; ++I) - RemoveSubRegionBindings(B, *I, M); - - B = Remove(B, R); -} - namespace { -class InvalidateRegionsWorker { +template <typename DERIVED> +class ClusterAnalysis { +protected: typedef BumpVector<BindingKey> RegionCluster; typedef llvm::DenseMap<const MemRegion *, RegionCluster *> ClusterMap; - typedef llvm::SmallVector<std::pair<const MemRegion *,RegionCluster*>, 10> - WorkList; + llvm::DenseMap<const RegionCluster*, unsigned> Visited; + typedef llvm::SmallVector<std::pair<const MemRegion *, RegionCluster*>, 10> + WorkList; BumpVectorContext BVC; ClusterMap ClusterM; WorkList WL; - + RegionStoreManager &RM; - StoreManager::InvalidatedSymbols *IS; ASTContext &Ctx; ValueManager &ValMgr; - + + RegionBindings B; + public: - InvalidateRegionsWorker(RegionStoreManager &rm, - StoreManager::InvalidatedSymbols *is, - ASTContext &ctx, ValueManager &valMgr) - : RM(rm), IS(is), Ctx(ctx), ValMgr(valMgr) {} - - Store InvalidateRegions(Store store, const MemRegion * const *I, - const MemRegion * const *E, - const Expr *Ex, unsigned Count); - -private: - void AddToWorkList(BindingKey K); - void AddToWorkList(const MemRegion *R); - void AddToCluster(BindingKey K); - RegionCluster **getCluster(const MemRegion *R); - void VisitBinding(SVal V); -}; -} + ClusterAnalysis(RegionStoreManager &rm, GRStateManager &StateMgr, + RegionBindings b) + : RM(rm), Ctx(StateMgr.getContext()), ValMgr(StateMgr.getValueManager()), + B(b) {} + + RegionBindings getRegionBindings() const { return B; } + + void AddToCluster(BindingKey K) { + const MemRegion *R = K.getRegion(); + const MemRegion *baseR = R->getBaseRegion(); + RegionCluster &C = getCluster(baseR); + C.push_back(K, BVC); + static_cast<DERIVED*>(this)->VisitAddedToCluster(baseR, C); + } -void InvalidateRegionsWorker::AddToCluster(BindingKey K) { - const MemRegion *R = K.getRegion(); - const MemRegion *baseR = R->getBaseRegion(); - RegionCluster **CPtr = getCluster(baseR); - assert(*CPtr); - (*CPtr)->push_back(K, BVC); -} + bool isVisited(const MemRegion *R) { + return (bool) Visited[&getCluster(R->getBaseRegion())]; + } -void InvalidateRegionsWorker::AddToWorkList(BindingKey K) { - AddToWorkList(K.getRegion()); -} + RegionCluster& getCluster(const MemRegion *R) { + RegionCluster *&CRef = ClusterM[R]; + if (!CRef) { + void *Mem = BVC.getAllocator().template Allocate<RegionCluster>(); + CRef = new (Mem) RegionCluster(BVC, 10); + } + return *CRef; + } -void InvalidateRegionsWorker::AddToWorkList(const MemRegion *R) { - const MemRegion *baseR = R->getBaseRegion(); - RegionCluster **CPtr = getCluster(baseR); - if (RegionCluster *C = *CPtr) { - WL.push_back(std::make_pair(baseR, C)); - *CPtr = NULL; + void GenerateClusters() { + // Scan the entire set of bindings and make the region clusters. + for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){ + AddToCluster(RI.getKey()); + if (const MemRegion *R = RI.getData().getAsRegion()) { + // Generate a cluster, but don't add the region to the cluster + // if there aren't any bindings. + getCluster(R->getBaseRegion()); + } + } + } + + bool AddToWorkList(const MemRegion *R, RegionCluster &C) { + if (unsigned &visited = Visited[&C]) + return false; + else + visited = 1; + + WL.push_back(std::make_pair(R, &C)); + return true; + } + + bool AddToWorkList(BindingKey K) { + return AddToWorkList(K.getRegion()); } -} -InvalidateRegionsWorker::RegionCluster ** -InvalidateRegionsWorker::getCluster(const MemRegion *R) { - RegionCluster *&CRef = ClusterM[R]; - if (!CRef) { - void *Mem = BVC.getAllocator().Allocate<RegionCluster>(); - CRef = new (Mem) RegionCluster(BVC, 10); + bool AddToWorkList(const MemRegion *R) { + const MemRegion *baseR = R->getBaseRegion(); + return AddToWorkList(baseR, getCluster(baseR)); + } + + void RunWorkList() { + while (!WL.empty()) { + const MemRegion *baseR; + RegionCluster *C; + llvm::tie(baseR, C) = WL.back(); + WL.pop_back(); + + // First visit the cluster. + static_cast<DERIVED*>(this)->VisitCluster(baseR, C->begin(), C->end()); + + // Next, visit the region. + static_cast<DERIVED*>(this)->VisitRegion(baseR); + } } - return &CRef; + +public: + void VisitAddedToCluster(const MemRegion *baseR, RegionCluster &C) {} + void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E) {} + void VisitRegion(const MemRegion *baseR) {} +}; +} + +//===----------------------------------------------------------------------===// +// Binding invalidation. +//===----------------------------------------------------------------------===// + +void RegionStoreManager::RemoveSubRegionBindings(RegionBindings &B, + const MemRegion *R, + RegionStoreSubRegionMap &M) { + + if (const RegionStoreSubRegionMap::Set *S = M.getSubRegions(R)) + for (RegionStoreSubRegionMap::Set::iterator I = S->begin(), E = S->end(); + I != E; ++I) + RemoveSubRegionBindings(B, *I, M); + + B = Remove(B, R); +} + +namespace { +class InvalidateRegionsWorker : public ClusterAnalysis<InvalidateRegionsWorker> +{ + const Expr *Ex; + unsigned Count; + StoreManager::InvalidatedSymbols *IS; +public: + InvalidateRegionsWorker(RegionStoreManager &rm, + GRStateManager &stateMgr, + RegionBindings b, + const Expr *ex, unsigned count, + StoreManager::InvalidatedSymbols *is) + : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr, b), + Ex(ex), Count(count), IS(is) {} + + void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E); + void VisitRegion(const MemRegion *baseR); + +private: + void VisitBinding(SVal V); +}; } void InvalidateRegionsWorker::VisitBinding(SVal V) { @@ -535,7 +590,7 @@ void InvalidateRegionsWorker::VisitBinding(SVal V) { if (IS) if (SymbolRef Sym = V.getAsSymbol()) IS->insert(Sym); - + if (const MemRegion *R = V.getAsRegion()) { AddToWorkList(R); return; @@ -558,112 +613,82 @@ void InvalidateRegionsWorker::VisitBinding(SVal V) { } } -Store InvalidateRegionsWorker::InvalidateRegions(Store store, - const MemRegion * const *I, - const MemRegion * const *E, - const Expr *Ex, unsigned Count) -{ - RegionBindings B = RegionStoreManager::GetRegionBindings(store); - - // Scan the entire store and make the region clusters. - for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) { - AddToCluster(RI.getKey()); - if (const MemRegion *R = RI.getData().getAsRegion()) { - // Generate a cluster, but don't add the region to the cluster - // if there aren't any bindings. - getCluster(R->getBaseRegion()); - } +void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR, + BindingKey *I, BindingKey *E) { + for ( ; I != E; ++I) { + // Get the old binding. Is it a region? If so, add it to the worklist. + const BindingKey &K = *I; + if (const SVal *V = RM.Lookup(B, K)) + VisitBinding(*V); + + B = RM.Remove(B, K); } - - // Add the cluster for I .. E to a worklist. - for ( ; I != E; ++I) - AddToWorkList(*I); +} - while (!WL.empty()) { - const MemRegion *baseR; - RegionCluster *C; - llvm::tie(baseR, C) = WL.back(); - WL.pop_back(); - - for (RegionCluster::iterator I = C->begin(), E = C->end(); I != E; ++I) { - BindingKey K = *I; - - // Get the old binding. Is it a region? If so, add it to the worklist. - if (const SVal *V = RM.Lookup(B, K)) - VisitBinding(*V); - - B = RM.Remove(B, K); - } - - // Now inspect the base region. +void InvalidateRegionsWorker::VisitRegion(const MemRegion *baseR) { + if (IS) { + // Symbolic region? Mark that symbol touched by the invalidation. + if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) + IS->insert(SR->getSymbol()); + } - if (IS) { - // Symbolic region? Mark that symbol touched by the invalidation. - if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) - IS->insert(SR->getSymbol()); + // BlockDataRegion? If so, invalidate captured variables that are passed + // by reference. + if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) { + for (BlockDataRegion::referenced_vars_iterator + BI = BR->referenced_vars_begin(), BE = BR->referenced_vars_end() ; + BI != BE; ++BI) { + const VarRegion *VR = *BI; + const VarDecl *VD = VR->getDecl(); + if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage()) + AddToWorkList(VR); } - - // BlockDataRegion? If so, invalidate captured variables that are passed - // by reference. - if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) { - for (BlockDataRegion::referenced_vars_iterator - BI = BR->referenced_vars_begin(), BE = BR->referenced_vars_end() ; - BI != BE; ++BI) { - const VarRegion *VR = *BI; - const VarDecl *VD = VR->getDecl(); - if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage()) - AddToWorkList(VR); - } - continue; - } - - if (isa<AllocaRegion>(baseR) || isa<SymbolicRegion>(baseR)) { - // Invalidate the region by setting its default value to - // conjured symbol. The type of the symbol is irrelavant. - DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy, - Count); - B = RM.Add(B, baseR, BindingKey::Default, V); - continue; - } - - if (!baseR->isBoundable()) - continue; - - const TypedRegion *TR = cast<TypedRegion>(baseR); - QualType T = TR->getValueType(Ctx); - - // Invalidate the binding. - if (const RecordType *RT = T->getAsStructureType()) { - const RecordDecl *RD = RT->getDecl()->getDefinition(); + return; + } + + if (isa<AllocaRegion>(baseR) || isa<SymbolicRegion>(baseR)) { + // Invalidate the region by setting its default value to + // conjured symbol. The type of the symbol is irrelavant. + DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy, + Count); + B = RM.Add(B, baseR, BindingKey::Default, V); + return; + } + + if (!baseR->isBoundable()) + return; + + const TypedRegion *TR = cast<TypedRegion>(baseR); + QualType T = TR->getValueType(Ctx); + + // Invalidate the binding. + if (const RecordType *RT = T->getAsStructureType()) { + const RecordDecl *RD = RT->getDecl()->getDefinition(); // No record definition. There is nothing we can do. - if (!RD) { - B = RM.Remove(B, baseR); - continue; - } - + if (!RD) { + B = RM.Remove(B, baseR); + return; + } + // Invalidate the region by setting its default value to // conjured symbol. The type of the symbol is irrelavant. - DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy, - Count); - B = RM.Add(B, baseR, BindingKey::Default, V); - continue; - } + DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy, + Count); + B = RM.Add(B, baseR, BindingKey::Default, V); + return; + } - if (const ArrayType *AT = Ctx.getAsArrayType(T)) { + if (const ArrayType *AT = Ctx.getAsArrayType(T)) { // Set the default value of the array to conjured symbol. - DefinedOrUnknownSVal V = - ValMgr.getConjuredSymbolVal(baseR, Ex, AT->getElementType(), Count); - B = RM.Add(B, baseR, BindingKey::Default, V); - continue; - } - - DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, T, Count); - assert(SymbolManager::canSymbolicate(T) || V.isUnknown()); - B = RM.Add(B, baseR, BindingKey::Direct, V); + DefinedOrUnknownSVal V = + ValMgr.getConjuredSymbolVal(baseR, Ex, AT->getElementType(), Count); + B = RM.Add(B, baseR, BindingKey::Default, V); + return; } - // Create a new state with the updated bindings. - return B.getRoot(); + DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, T, Count); + assert(SymbolManager::canSymbolicate(T) || V.isUnknown()); + B = RM.Add(B, baseR, BindingKey::Direct, V); } Store RegionStoreManager::InvalidateRegions(Store store, @@ -671,11 +696,23 @@ Store RegionStoreManager::InvalidateRegions(Store store, const MemRegion * const *E, const Expr *Ex, unsigned Count, InvalidatedSymbols *IS) { - InvalidateRegionsWorker W(*this, IS, getContext(), - StateMgr.getValueManager()); - return W.InvalidateRegions(store, I, E, Ex, Count); + InvalidateRegionsWorker W(*this, StateMgr, + RegionStoreManager::GetRegionBindings(store), + Ex, Count, IS); + + // Scan the bindings and generate the clusters. + W.GenerateClusters(); + + // Add I .. E to the worklist. + for ( ; I != E; ++I) + W.AddToWorkList(*I); + + W.RunWorkList(); + + // Return the new bindings. + return W.getRegionBindings().getRoot(); } - + //===----------------------------------------------------------------------===// // Extents for regions. //===----------------------------------------------------------------------===// @@ -686,7 +723,7 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state, switch (R->getKind()) { case MemRegion::CXXThisRegionKind: - assert(0 && "Cannot get size of 'this' region"); + assert(0 && "Cannot get size of 'this' region"); case MemRegion::GenericMemSpaceRegionKind: case MemRegion::StackLocalsSpaceRegionKind: case MemRegion::StackArgumentsSpaceRegionKind: @@ -719,7 +756,7 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state, if (!CI) return UnknownVal(); - CharUnits RegionSize = + CharUnits RegionSize = CharUnits::fromQuantity(CI->getValue().getSExtValue()); CharUnits EleSize = getContext().getTypeSizeInChars(EleTy); assert(RegionSize % EleSize == 0); @@ -840,7 +877,7 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R, // Not yet handled. case MemRegion::VarRegionKind: case MemRegion::StringRegionKind: { - + } // Fall-through. case MemRegion::CompoundLiteralRegionKind: @@ -884,13 +921,13 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R, MRMgr.getElementRegion(ER->getElementType(), NewIdx, ER->getSuperRegion(), getContext()); return ValMgr.makeLoc(NewER); - } + } if (0 == Base->getValue()) { const MemRegion* NewER = MRMgr.getElementRegion(ER->getElementType(), R, ER->getSuperRegion(), getContext()); - return ValMgr.makeLoc(NewER); - } + return ValMgr.makeLoc(NewER); + } } return UnknownVal(); @@ -900,10 +937,10 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R, // Loading values from regions. //===----------------------------------------------------------------------===// -Optional<SVal> RegionStoreManager::getDirectBinding(RegionBindings B, +Optional<SVal> RegionStoreManager::getDirectBinding(RegionBindings B, const MemRegion *R) { if (const SVal *V = Lookup(B, R, BindingKey::Direct)) - return *V; + return *V; return Optional<SVal>(); } @@ -923,10 +960,10 @@ Optional<SVal> RegionStoreManager::getDefaultBinding(RegionBindings B, Optional<SVal> RegionStoreManager::getBinding(RegionBindings B, const MemRegion *R) { - + if (Optional<SVal> V = getDirectBinding(B, R)) return V; - + return getDefaultBinding(B, R); } @@ -964,12 +1001,12 @@ RegionStoreManager::GetElementZeroRegion(const MemRegion *R, QualType T) { SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) { assert(!isa<UnknownVal>(L) && "location unknown"); assert(!isa<UndefinedVal>(L) && "location undefined"); - + // FIXME: Is this even possible? Shouldn't this be treated as a null // dereference at a higher level? if (isa<loc::ConcreteInt>(L)) return UndefinedVal(); - + const MemRegion *MR = cast<loc::MemRegionVal>(L).getRegion(); if (isa<AllocaRegion>(MR) || isa<SymbolicRegion>(MR)) @@ -1029,7 +1066,7 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) { // bound regions (e.g., several bound bytes), or could be a subset of // a larger value. return CastRetrievedVal(RetrieveElement(store, ER), ER, T, false); - } + } if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) { // FIXME: Here we actually perform an implicit conversion from the loaded @@ -1047,7 +1084,7 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) { // that blow past the extent of the variable. If the address of the // variable is reinterpretted, it is possible we stored a different value // that could fit within the variable. Either we need to cast these when - // storing them or reinterpret them lazily (as we do here). + // storing them or reinterpret them lazily (as we do here). return CastRetrievedVal(RetrieveVar(store, VR), VR, T, false); } @@ -1096,7 +1133,7 @@ RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R) { return std::make_pair(X.first, MRMgr.getFieldRegionWithSuper(FR, X.second)); } - // The NULL MemRegion indicates an non-existent lazy binding. A NULL Store is + // The NULL MemRegion indicates an non-existent lazy binding. A NULL Store is // possible for a valid lazy binding. return std::make_pair((Store) 0, (const MemRegion *) 0); } @@ -1112,13 +1149,13 @@ SVal RegionStoreManager::RetrieveElement(Store store, // Check if the region is an element region of a string literal. if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) { - // FIXME: Handle loads from strings where the literal is treated as + // FIXME: Handle loads from strings where the literal is treated as // an integer, e.g., *((unsigned int*)"hello") ASTContext &Ctx = getContext(); QualType T = Ctx.getAsArrayType(StrR->getValueType(Ctx))->getElementType(); if (T != Ctx.getCanonicalType(R->getElementType())) return UnknownVal(); - + const StringLiteral *Str = StrR->getStringLiteral(); SVal Idx = R->getIndex(); if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Idx)) { @@ -1155,7 +1192,7 @@ SVal RegionStoreManager::RetrieveElement(Store store, // Other cases: give up. return UnknownVal(); } - + return RetrieveFieldOrElementCommon(store, R, R->getElementType(), superR); } @@ -1268,8 +1305,8 @@ SVal RegionStoreManager::RetrieveVar(Store store, const VarRegion *R) { const VarDecl *VD = R->getDecl(); QualType T = VD->getType(); const MemSpaceRegion *MS = R->getMemorySpace(); - - if (isa<UnknownSpaceRegion>(MS) || + + if (isa<UnknownSpaceRegion>(MS) || isa<StackArgumentsSpaceRegion>(MS)) return ValMgr.getRegionValueSymbolVal(R); @@ -1282,9 +1319,9 @@ SVal RegionStoreManager::RetrieveVar(Store store, const VarRegion *R) { if (T->isPointerType()) return ValMgr.makeNull(); - return UnknownVal(); + return UnknownVal(); } - + return UndefinedVal(); } @@ -1402,7 +1439,7 @@ Store RegionStoreManager::Bind(Store store, Loc L, SVal V) { // Binding directly to a symbolic region should be treated as binding // to element 0. QualType T = SR->getSymbol()->getType(getContext()); - + // FIXME: Is this the right way to handle symbols that are references? if (const PointerType *PT = T->getAs<PointerType>()) T = PT->getPointeeType(); @@ -1417,7 +1454,7 @@ Store RegionStoreManager::Bind(Store store, Loc L, SVal V) { return Add(B, R, BindingKey::Direct, V).getRoot(); } -Store RegionStoreManager::BindDecl(Store store, const VarRegion *VR, +Store RegionStoreManager::BindDecl(Store store, const VarRegion *VR, SVal InitVal) { QualType T = VR->getDecl()->getType(); @@ -1460,19 +1497,19 @@ Store RegionStoreManager::setImplicitDefaultValue(Store store, return Add(B, R, BindingKey::Default, V).getRoot(); } - -Store RegionStoreManager::BindArray(Store store, const TypedRegion* R, + +Store RegionStoreManager::BindArray(Store store, const TypedRegion* R, SVal Init) { - + ASTContext &Ctx = getContext(); const ArrayType *AT = cast<ArrayType>(Ctx.getCanonicalType(R->getValueType(Ctx))); - QualType ElementTy = AT->getElementType(); + QualType ElementTy = AT->getElementType(); Optional<uint64_t> Size; - + if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT)) Size = CAT->getSize().getZExtValue(); - + // Check if the init expr is a StringLiteral. if (isa<loc::MemRegionVal>(Init)) { const MemRegion* InitR = cast<loc::MemRegionVal>(Init).getRegion(); @@ -1484,11 +1521,11 @@ Store RegionStoreManager::BindArray(Store store, const TypedRegion* R, // Copy bytes from the string literal into the target array. Trailing bytes // in the array that are not covered by the string literal are initialized // to zero. - + // We assume that string constants are bound to // constant arrays. uint64_t size = Size.getValue(); - + for (uint64_t i = 0; i < size; ++i, ++j) { if (j >= len) break; @@ -1509,10 +1546,10 @@ Store RegionStoreManager::BindArray(Store store, const TypedRegion* R, return CopyLazyBindings(*LCV, store, R); // Remaining case: explicit compound values. - + if (Init.isUnknown()) - return setImplicitDefaultValue(store, R, ElementTy); - + return setImplicitDefaultValue(store, R, ElementTy); + nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init); nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end(); uint64_t i = 0; @@ -1628,14 +1665,14 @@ Store RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V, BindingKey BindingKey::Make(const MemRegion *R, Kind k) { if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { const RegionRawOffset &O = ER->getAsRawOffset(); - + if (O.getRegion()) return BindingKey(O.getRegion(), O.getByteOffset(), k); - + // FIXME: There are some ElementRegions for which we cannot compute // raw offsets yet, including regions with symbolic offsets. } - + return BindingKey(R, 0, k); } @@ -1675,194 +1712,163 @@ Store RegionStoreManager::Remove(Store store, BindingKey K) { //===----------------------------------------------------------------------===// // State pruning. //===----------------------------------------------------------------------===// - -Store RegionStoreManager::RemoveDeadBindings(Store store, Stmt* Loc, - SymbolReaper& SymReaper, - llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) -{ - typedef std::pair<Store, const MemRegion *> RBDNode; - RegionBindings B = GetRegionBindings(store); +namespace { +class RemoveDeadBindingsWorker : + public ClusterAnalysis<RemoveDeadBindingsWorker> { + llvm::SmallVector<const SymbolicRegion*, 12> Postponed; + SymbolReaper &SymReaper; + Stmt *Loc; +public: + RemoveDeadBindingsWorker(RegionStoreManager &rm, GRStateManager &stateMgr, + RegionBindings b, SymbolReaper &symReaper, + Stmt *loc) + : ClusterAnalysis<RemoveDeadBindingsWorker>(rm, stateMgr, b), + SymReaper(symReaper), Loc(loc) {} + + // Called by ClusterAnalysis. + void VisitAddedToCluster(const MemRegion *baseR, RegionCluster &C); + void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E); + void VisitRegion(const MemRegion *baseR); + + bool UpdatePostponed(); + void VisitBinding(SVal V); +}; +} - // The backmap from regions to subregions. - llvm::OwningPtr<RegionStoreSubRegionMap> - SubRegions(getRegionStoreSubRegionMap(store)); - - // Do a pass over the regions in the store. For VarRegions we check if - // the variable is still live and if so add it to the list of live roots. - // For other regions we populate our region backmap. - llvm::SmallVector<const MemRegion*, 10> IntermediateRoots; - - // Scan the direct bindings for "intermediate" roots. - for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) { - const MemRegion *R = I.getKey().getRegion(); - IntermediateRoots.push_back(R); - } - - // Process the "intermediate" roots to find if they are referenced by - // real roots. - llvm::SmallVector<RBDNode, 10> WorkList; - llvm::SmallVector<RBDNode, 10> Postponed; - - llvm::DenseSet<const MemRegion*> IntermediateVisited; - - while (!IntermediateRoots.empty()) { - const MemRegion* R = IntermediateRoots.back(); - IntermediateRoots.pop_back(); - - if (IntermediateVisited.count(R)) - continue; - IntermediateVisited.insert(R); - - if (const VarRegion* VR = dyn_cast<VarRegion>(R)) { - if (SymReaper.isLive(Loc, VR)) - WorkList.push_back(std::make_pair(store, VR)); - continue; - } - - if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) { - llvm::SmallVectorImpl<RBDNode> &Q = - SymReaper.isLive(SR->getSymbol()) ? WorkList : Postponed; - - Q.push_back(std::make_pair(store, SR)); +void RemoveDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR, + RegionCluster &C) { - continue; - } - - // Add the super region for R to the worklist if it is a subregion. - if (const SubRegion* superR = - dyn_cast<SubRegion>(cast<SubRegion>(R)->getSuperRegion())) - IntermediateRoots.push_back(superR); + if (const VarRegion *VR = dyn_cast<VarRegion>(baseR)) { + if (SymReaper.isLive(Loc, VR)) + AddToWorkList(baseR, C); + + return; } - // Enqueue the RegionRoots onto WorkList. - for (llvm::SmallVectorImpl<const MemRegion*>::iterator I=RegionRoots.begin(), - E=RegionRoots.end(); I!=E; ++I) { - WorkList.push_back(std::make_pair(store, *I)); - } - RegionRoots.clear(); - - llvm::DenseSet<RBDNode> Visited; - -tryAgain: - while (!WorkList.empty()) { - RBDNode N = WorkList.back(); - WorkList.pop_back(); - - // Have we visited this node before? - if (Visited.count(N)) - continue; - Visited.insert(N); - - const MemRegion *R = N.second; - Store store_N = N.first; - - // Enqueue subregions. - RegionStoreSubRegionMap *M; - - if (store == store_N) - M = SubRegions.get(); - else { - RegionStoreSubRegionMap *& SM = SC[store_N]; - if (!SM) - SM = getRegionStoreSubRegionMap(store_N); - M = SM; - } + if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) { + if (SymReaper.isLive(SR->getSymbol())) + AddToWorkList(SR, C); + else + Postponed.push_back(SR); - if (const RegionStoreSubRegionMap::Set *S = M->getSubRegions(R)) - for (RegionStoreSubRegionMap::Set::iterator I = S->begin(), E = S->end(); - I != E; ++I) - WorkList.push_back(std::make_pair(store_N, *I)); - - // Enqueue the super region. - if (const SubRegion *SR = dyn_cast<SubRegion>(R)) { - const MemRegion *superR = SR->getSuperRegion(); - if (!isa<MemSpaceRegion>(superR)) { - // If 'R' is a field or an element, we want to keep the bindings - // for the other fields and elements around. The reason is that - // pointer arithmetic can get us to the other fields or elements. - assert(isa<FieldRegion>(R) || isa<ElementRegion>(R) - || isa<ObjCIvarRegion>(R)); - WorkList.push_back(std::make_pair(store_N, superR)); - } - } + return; + } +} - // Mark the symbol for any live SymbolicRegion as "live". This means we - // should continue to track that symbol. - if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R)) - SymReaper.markLive(SymR->getSymbol()); - - // For BlockDataRegions, enqueue the VarRegions for variables marked - // with __block (passed-by-reference). - // via BlockDeclRefExprs. - if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(R)) { - for (BlockDataRegion::referenced_vars_iterator - RI = BD->referenced_vars_begin(), RE = BD->referenced_vars_end(); - RI != RE; ++RI) { - if ((*RI)->getDecl()->getAttr<BlocksAttr>()) - WorkList.push_back(std::make_pair(store_N, *RI)); - } - // No possible data bindings on a BlockDataRegion. Continue to the - // next region in the worklist. - continue; +void RemoveDeadBindingsWorker::VisitCluster(const MemRegion *baseR, + BindingKey *I, BindingKey *E) { + for ( ; I != E; ++I) { + const MemRegion *R = I->getRegion(); + if (R != baseR) + VisitRegion(R); + } +} + +void RemoveDeadBindingsWorker::VisitBinding(SVal V) { + // Is it a LazyCompoundVal? All referenced regions are live as well. + if (const nonloc::LazyCompoundVal *LCS = + dyn_cast<nonloc::LazyCompoundVal>(&V)) { + + const MemRegion *LazyR = LCS->getRegion(); + RegionBindings B = RegionStoreManager::GetRegionBindings(LCS->getStore()); + for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){ + const MemRegion *baseR = RI.getKey().getRegion(); + if (cast<SubRegion>(baseR)->isSubRegionOf(LazyR)) + VisitBinding(RI.getData()); } + return; + } - RegionBindings B_N = GetRegionBindings(store_N); - - // Get the data binding for R (if any). - Optional<SVal> V = getBinding(B_N, R); - - if (V) { - // Check for lazy bindings. - if (const nonloc::LazyCompoundVal *LCV = - dyn_cast<nonloc::LazyCompoundVal>(V.getPointer())) { - - const LazyCompoundValData *D = LCV->getCVData(); - WorkList.push_back(std::make_pair(D->getStore(), D->getRegion())); - } - else { - // Update the set of live symbols. - for (SVal::symbol_iterator SI=V->symbol_begin(), SE=V->symbol_end(); - SI!=SE;++SI) - SymReaper.markLive(*SI); - - // If V is a region, then add it to the worklist. - if (const MemRegion *RX = V->getAsRegion()) - WorkList.push_back(std::make_pair(store_N, RX)); - } + // If V is a region, then add it to the worklist. + if (const MemRegion *R = V.getAsRegion()) + AddToWorkList(R); + + // Update the set of live symbols. + for (SVal::symbol_iterator SI=V.symbol_begin(), SE=V.symbol_end(); + SI!=SE;++SI) + SymReaper.markLive(*SI); +} + +void RemoveDeadBindingsWorker::VisitRegion(const MemRegion *R) { + // Mark this region "live" by adding it to the worklist. This will cause + // use to visit all regions in the cluster (if we haven't visited them + // already). + AddToWorkList(R); + + // Mark the symbol for any live SymbolicRegion as "live". This means we + // should continue to track that symbol. + if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R)) + SymReaper.markLive(SymR->getSymbol()); + + // For BlockDataRegions, enqueue the VarRegions for variables marked + // with __block (passed-by-reference). + // via BlockDeclRefExprs. + if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(R)) { + for (BlockDataRegion::referenced_vars_iterator + RI = BD->referenced_vars_begin(), RE = BD->referenced_vars_end(); + RI != RE; ++RI) { + if ((*RI)->getDecl()->getAttr<BlocksAttr>()) + AddToWorkList(*RI); } + + // No possible data bindings on a BlockDataRegion. + return; } - + + // Get the data binding for R (if any). + if (Optional<SVal> V = RM.getBinding(B, R)) + VisitBinding(*V); +} + +bool RemoveDeadBindingsWorker::UpdatePostponed() { // See if any postponed SymbolicRegions are actually live now, after // having done a scan. - for (llvm::SmallVectorImpl<RBDNode>::iterator I = Postponed.begin(), - E = Postponed.end() ; I != E ; ++I) { - if (const SymbolicRegion *SR = cast_or_null<SymbolicRegion>(I->second)) { + bool changed = false; + + for (llvm::SmallVectorImpl<const SymbolicRegion*>::iterator + I = Postponed.begin(), E = Postponed.end() ; I != E ; ++I) { + if (const SymbolicRegion *SR = cast_or_null<SymbolicRegion>(*I)) { if (SymReaper.isLive(SR->getSymbol())) { - WorkList.push_back(*I); - I->second = NULL; + changed |= AddToWorkList(SR); + *I = NULL; } } } - - if (!WorkList.empty()) - goto tryAgain; - + + return changed; +} + +Store RegionStoreManager::RemoveDeadBindings(Store store, Stmt* Loc, + SymbolReaper& SymReaper, + llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) +{ + RegionBindings B = GetRegionBindings(store); + RemoveDeadBindingsWorker W(*this, StateMgr, B, SymReaper, Loc); + W.GenerateClusters(); + + // Enqueue the region roots onto the worklist. + for (llvm::SmallVectorImpl<const MemRegion*>::iterator I=RegionRoots.begin(), + E=RegionRoots.end(); I!=E; ++I) + W.AddToWorkList(*I); + + do W.RunWorkList(); while (W.UpdatePostponed()); + // We have now scanned the store, marking reachable regions and symbols // as live. We now remove all the regions that are dead from the store // as well as update DSymbols with the set symbols that are now dead. - Store new_store = store; for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) { - const MemRegion* R = I.getKey().getRegion(); - // If this region live? Is so, none of its symbols are dead. - if (Visited.count(std::make_pair(store, R))) + const BindingKey &K = I.getKey(); + + // If the cluster has been visited, we know the region has been marked. + if (W.isVisited(K.getRegion())) continue; - // Remove this dead region from the store. - new_store = Remove(new_store, I.getKey()); + // Remove the dead entry. + B = Remove(B, K); - // Mark all non-live symbols that this region references as dead. - if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R)) + // Mark all non-live symbols that this binding references as dead. + if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(K.getRegion())) SymReaper.maybeDead(SymR->getSymbol()); SVal X = I.getData(); @@ -1871,9 +1877,10 @@ tryAgain: SymReaper.maybeDead(*SI); } - return new_store; + return B.getRoot(); } + GRState const *RegionStoreManager::EnterStackFrame(GRState const *state, StackFrameContext const *frame) { FunctionDecl const *FD = cast<FunctionDecl>(frame->getDecl()); diff --git a/lib/Checker/SVals.cpp b/lib/Checker/SVals.cpp index 28b3fce050bb..4bfa2cdafb46 100644 --- a/lib/Checker/SVals.cpp +++ b/lib/Checker/SVals.cpp @@ -70,6 +70,25 @@ SymbolRef SVal::getAsLocSymbol() const { return NULL; } +/// Get the symbol in the SVal or its base region. +SymbolRef SVal::getLocSymbolInBase() const { + const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this); + + if (!X) + return 0; + + const MemRegion *R = X->getRegion(); + + while (const SubRegion *SR = dyn_cast<SubRegion>(R)) { + if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SR)) + return SymR->getSymbol(); + else + R = SR->getSuperRegion(); + } + + return 0; +} + /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef. /// Otherwise return 0. // FIXME: should we consider SymbolRef wrapped in CodeTextRegion? diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 0f3502e9bea3..c3302e661dfb 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -36,8 +36,9 @@ using namespace clang; using namespace clang::CodeGen; CGDebugInfo::CGDebugInfo(CodeGenModule &CGM) - : CGM(CGM), isMainCompileUnitCreated(false), DebugFactory(CGM.getModule()), - BlockLiteralGenericSet(false) { + : CGM(CGM), DebugFactory(CGM.getModule()), + FwdDeclCount(0), BlockLiteralGenericSet(false) { + CreateCompileUnit(); } CGDebugInfo::~CGDebugInfo() { @@ -85,45 +86,29 @@ llvm::StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) { return llvm::StringRef(StrPtr, NS.length()); } -/// getOrCreateCompileUnit - Get the compile unit from the cache or create a new -/// one if necessary. This returns null for invalid source locations. -llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) { - // Get source file information. - const char *FileName = "<unknown>"; +/// getOrCreateFile - Get the file debug info descriptor for the input location. +llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) { + if (!Loc.isValid()) + // If Location is not valid then use main input file. + return DebugFactory.CreateFile(TheCU.getFilename(), TheCU.getDirectory(), + TheCU); SourceManager &SM = CGM.getContext().getSourceManager(); - if (Loc.isValid()) { - PresumedLoc PLoc = SM.getPresumedLoc(Loc); - FileName = PLoc.getFilename(); - unsigned FID = PLoc.getIncludeLoc().getRawEncoding(); - - // See if this compile unit has been used before for this valid location. - llvm::DICompileUnit &Unit = CompileUnitCache[FID]; - if (!Unit.isNull()) return Unit; - } + PresumedLoc PLoc = SM.getPresumedLoc(Loc); + llvm::sys::Path AbsFileName(PLoc.getFilename()); + AbsFileName.makeAbsolute(); + + return DebugFactory.CreateFile(AbsFileName.getLast(), + AbsFileName.getDirname(), TheCU); +} +/// CreateCompileUnit - Create new compile unit. +void CGDebugInfo::CreateCompileUnit() { // Get absolute path name. - llvm::sys::Path AbsFileName(FileName); + llvm::sys::Path AbsFileName(CGM.getCodeGenOpts().MainFileName); AbsFileName.makeAbsolute(); - // See if thie compile unit is representing main source file. Each source - // file has corresponding compile unit. There is only one main source - // file at a time. - bool isMain = false; - const LangOptions &LO = CGM.getLangOptions(); - const CodeGenOptions &CGO = CGM.getCodeGenOpts(); - if (isMainCompileUnitCreated == false) { - if (!CGO.MainFileName.empty()) { - if (AbsFileName.getLast() == CGO.MainFileName) - isMain = true; - } else { - if (Loc.isValid() && SM.isFromMainFile(Loc)) - isMain = true; - } - if (isMain) - isMainCompileUnitCreated = true; - } - unsigned LangTag; + const LangOptions &LO = CGM.getLangOptions(); if (LO.CPlusPlus) { if (LO.ObjC1) LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus; @@ -149,22 +134,15 @@ llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) { RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1; // Create new compile unit. - llvm::DICompileUnit Unit = DebugFactory.CreateCompileUnit( - LangTag, AbsFileName.getLast(), AbsFileName.getDirname(), Producer, isMain, + TheCU = DebugFactory.CreateCompileUnit( + LangTag, AbsFileName.getLast(), AbsFileName.getDirname(), Producer, true, LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers); - - if (Loc.isValid()) { - PresumedLoc PLoc = SM.getPresumedLoc(Loc); - unsigned FID = PLoc.getIncludeLoc().getRawEncoding(); - CompileUnitCache[FID] = Unit; - } - return Unit; } /// CreateType - Get the Basic type from the cache or create a new /// one if necessary. llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { unsigned Encoding = 0; switch (BT->getKind()) { default: @@ -201,7 +179,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT, } llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { // Bit size, align and offset of the type. unsigned Encoding = llvm::dwarf::DW_ATE_complex_float; if (Ty->isComplexIntegerType()) @@ -220,7 +198,7 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty, /// CreateCVRType - Get the qualified type from the cache or create /// a new one if necessary. -llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DICompileUnit Unit) { +llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) { QualifierCollector Qc; const Type *T = Qc.strip(Ty); @@ -250,13 +228,13 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DICompileUnit U // No need to fill in the Name, Line, Size, Alignment, Offset in case of // CVR derived types. llvm::DIType DbgTy = - DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(), + DebugFactory.CreateDerivedType(Tag, Unit, "", Unit, 0, 0, 0, 0, 0, FromTy); return DbgTy; } llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { llvm::DIType DbgTy = CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty, Ty->getPointeeType(), Unit); @@ -264,7 +242,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty, } llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty, Ty->getPointeeType(), Unit); } @@ -272,7 +250,7 @@ llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty, llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag, const Type *Ty, QualType PointeeTy, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { llvm::DIType EltTy = getOrCreateType(PointeeTy, Unit); // Bit size, align and offset of the type. @@ -284,17 +262,16 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag, uint64_t Align = CGM.getContext().getTypeAlign(Ty); return - DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(), + DebugFactory.CreateDerivedType(Tag, Unit, "", Unit, 0, Size, Align, 0, 0, EltTy); } llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { if (BlockLiteralGenericSet) return BlockLiteralGeneric; - llvm::DICompileUnit DefUnit; unsigned Tag = llvm::dwarf::DW_TAG_structure_type; llvm::SmallVector<llvm::DIDescriptor, 5> EltTys; @@ -314,7 +291,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "reserved", DefUnit, + "reserved", Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -325,7 +302,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "Size", DefUnit, + "Size", Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -337,7 +314,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, unsigned Flags = llvm::DIType::FlagAppleBlock; EltTy = DebugFactory.CreateCompositeType(Tag, Unit, "__block_descriptor", - DefUnit, 0, FieldOffset, 0, 0, Flags, + Unit, 0, FieldOffset, 0, 0, Flags, llvm::DIType(), Elements); // Bit size, align and offset of the type. @@ -345,7 +322,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, uint64_t Align = CGM.getContext().getTypeAlign(Ty); DescTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, - Unit, "", llvm::DICompileUnit(), + Unit, "", Unit, 0, Size, Align, 0, 0, EltTy); FieldOffset = 0; @@ -354,7 +331,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "__isa", DefUnit, + "__isa", Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -365,7 +342,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "__flags", DefUnit, + "__flags", Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -376,7 +353,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "__reserved", DefUnit, + "__reserved", Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -387,7 +364,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "__FuncPtr", DefUnit, + "__FuncPtr", Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -398,7 +375,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, FieldSize = CGM.getContext().getTypeSize(Ty); FieldAlign = CGM.getContext().getTypeAlign(Ty); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "__descriptor", DefUnit, + "__descriptor", Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -407,19 +384,19 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); EltTy = DebugFactory.CreateCompositeType(Tag, Unit, "__block_literal_generic", - DefUnit, 0, FieldOffset, 0, 0, Flags, + Unit, 0, FieldOffset, 0, 0, Flags, llvm::DIType(), Elements); BlockLiteralGenericSet = true; BlockLiteralGeneric = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit, - "", llvm::DICompileUnit(), + "", Unit, 0, Size, Align, 0, 0, EltTy); return BlockLiteralGeneric; } llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { // Typedefs are derived from some other type. If we have a typedef of a // typedef, make sure to emit the whole chain. llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit); @@ -442,7 +419,7 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, } llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { llvm::SmallVector<llvm::DIDescriptor, 16> EltTys; // Add the result type at least. @@ -462,7 +439,7 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, llvm::DIType DbgTy = DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type, - Unit, "", llvm::DICompileUnit(), + Unit, "", Unit, 0, 0, 0, 0, 0, llvm::DIType(), EltTypeArray); return DbgTy; @@ -471,7 +448,7 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, /// CollectRecordFields - A helper function to collect debug info for /// record fields. This is used while creating debug info entry for a Record. void CGDebugInfo:: -CollectRecordFields(const RecordDecl *RD, llvm::DICompileUnit Unit, +CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit, llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys) { unsigned FieldNo = 0; SourceManager &SM = CGM.getContext().getSourceManager(); @@ -491,11 +468,11 @@ CollectRecordFields(const RecordDecl *RD, llvm::DICompileUnit Unit, // Get the location for the field. SourceLocation FieldDefLoc = Field->getLocation(); PresumedLoc PLoc = SM.getPresumedLoc(FieldDefLoc); - llvm::DICompileUnit FieldDefUnit; + llvm::DIFile FieldDefUnit; unsigned FieldLine = 0; if (!PLoc.isInvalid()) { - FieldDefUnit = getOrCreateCompileUnit(FieldDefLoc); + FieldDefUnit = getOrCreateFile(FieldDefLoc); FieldLine = PLoc.getLine(); } @@ -531,7 +508,7 @@ CollectRecordFields(const RecordDecl *RD, llvm::DICompileUnit Unit, /// routine to get a method type which includes "this" pointer. llvm::DIType CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { llvm::DIType FnTy = getOrCreateType(Method->getType(), Unit); // Static methods do not need "this" pointer argument. @@ -566,7 +543,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type, - Unit, "", llvm::DICompileUnit(), + Unit, "", Unit, 0, 0, 0, 0, 0, llvm::DIType(), EltTypeArray); } @@ -575,7 +552,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, /// a single member function GlobalDecl. llvm::DISubprogram CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, - llvm::DICompileUnit Unit, + llvm::DIFile Unit, llvm::DICompositeType &RecordTy) { bool IsCtorOrDtor = isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method); @@ -594,11 +571,11 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, // Get the location for the method. SourceLocation MethodDefLoc = Method->getLocation(); PresumedLoc PLoc = SM.getPresumedLoc(MethodDefLoc); - llvm::DICompileUnit MethodDefUnit; + llvm::DIFile MethodDefUnit; unsigned MethodLine = 0; if (!PLoc.isInvalid()) { - MethodDefUnit = getOrCreateCompileUnit(MethodDefLoc); + MethodDefUnit = getOrCreateFile(MethodDefLoc); MethodLine = PLoc.getLine(); } @@ -640,7 +617,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, /// C++ member functions.This is used while creating debug info entry for /// a Record. void CGDebugInfo:: -CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DICompileUnit Unit, +CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit, llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys, llvm::DICompositeType &RecordTy) { for(CXXRecordDecl::method_iterator I = RD->method_begin(), @@ -658,7 +635,7 @@ CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DICompileUnit Unit, /// C++ base classes. This is used while creating debug info entry for /// a Record. void CGDebugInfo:: -CollectCXXBases(const CXXRecordDecl *RD, llvm::DICompileUnit Unit, +CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit, llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys, llvm::DICompositeType &RecordTy) { @@ -688,7 +665,7 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DICompileUnit Unit, llvm::DIType DTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_inheritance, RecordTy, llvm::StringRef(), - llvm::DICompileUnit(), 0, 0, 0, + Unit, 0, 0, 0, BaseOffset, BFlags, getOrCreateType(BI->getType(), Unit)); @@ -697,8 +674,8 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DICompileUnit Unit, } /// getOrCreateVTablePtrType - Return debug info descriptor for vtable. -llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DICompileUnit Unit) { - if (!VTablePtrType.isNull()) +llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) { + if (VTablePtrType.isValid()) return VTablePtrType; ASTContext &Context = CGM.getContext(); @@ -710,18 +687,19 @@ llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DICompileUnit Unit) { DebugFactory.GetOrCreateArray(STys.data(), STys.size()); llvm::DIType SubTy = DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type, - Unit, "", llvm::DICompileUnit(), + Unit, "", Unit, 0, 0, 0, 0, 0, llvm::DIType(), SElements); unsigned Size = Context.getTypeSize(Context.VoidPtrTy); llvm::DIType vtbl_ptr_type = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, - Unit, "__vtbl_ptr_type", llvm::DICompileUnit(), + Unit, "__vtbl_ptr_type", Unit, 0, Size, 0, 0, 0, SubTy); - VTablePtrType = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, - Unit, "", llvm::DICompileUnit(), - 0, Size, 0, 0, 0, vtbl_ptr_type); + VTablePtrType = + DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, + Unit, "", Unit, + 0, Size, 0, 0, 0, vtbl_ptr_type); return VTablePtrType; } @@ -740,7 +718,7 @@ llvm::StringRef CGDebugInfo::getVtableName(const CXXRecordDecl *RD) { /// CollectVtableInfo - If the C++ class has vtable info then insert appropriate /// debug info entry in EltTys vector. void CGDebugInfo:: -CollectVtableInfo(const CXXRecordDecl *RD, llvm::DICompileUnit Unit, +CollectVtableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit, llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys) { const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); @@ -755,7 +733,7 @@ CollectVtableInfo(const CXXRecordDecl *RD, llvm::DICompileUnit Unit, unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); llvm::DIType VPTR = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - getVtableName(RD), llvm::DICompileUnit(), + getVtableName(RD), Unit, 0, Size, 0, 0, 0, getOrCreateVTablePtrType(Unit)); EltTys.push_back(VPTR); @@ -763,7 +741,7 @@ CollectVtableInfo(const CXXRecordDecl *RD, llvm::DICompileUnit Unit, /// CreateType - get structure or union type. llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { RecordDecl *RD = Ty->getDecl(); unsigned Tag; @@ -780,10 +758,10 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, // Get overall information about the record type for the debug info. PresumedLoc PLoc = SM.getPresumedLoc(RD->getLocation()); - llvm::DICompileUnit DefUnit; + llvm::DIFile DefUnit; unsigned Line = 0; if (!PLoc.isInvalid()) { - DefUnit = getOrCreateCompileUnit(RD->getLocation()); + DefUnit = getOrCreateFile(RD->getLocation()); Line = PLoc.getLine(); } @@ -796,12 +774,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, // A RD->getName() is not unique. However, the debug info descriptors // are uniqued so use type name to ensure uniquness. - std::string STy = QualType(Ty, 0).getAsString(); + llvm::SmallString<256> FwdDeclName; + FwdDeclName.resize(256); + sprintf(&FwdDeclName[0], "fwd.type.%d", FwdDeclCount++); llvm::DIDescriptor FDContext = getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()), Unit); llvm::DICompositeType FwdDecl = - DebugFactory.CreateCompositeType(Tag, FDContext, - STy.c_str(), + DebugFactory.CreateCompositeType(Tag, FDContext, FwdDeclName, DefUnit, Line, 0, 0, 0, 0, llvm::DIType(), llvm::DIArray()); @@ -861,19 +840,19 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, /// CreateType - get objective-c interface type. llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { ObjCInterfaceDecl *ID = Ty->getDecl(); unsigned Tag = llvm::dwarf::DW_TAG_structure_type; SourceManager &SM = CGM.getContext().getSourceManager(); // Get overall information about the record type for the debug info. - llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(ID->getLocation()); + llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation()); PresumedLoc PLoc = SM.getPresumedLoc(ID->getLocation()); unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine(); - unsigned RuntimeLang = DefUnit.getLanguage(); + unsigned RuntimeLang = TheCU.getLanguage(); // To handle recursive interface, we // first generate a debug descriptor for the struct as a forward declaration. @@ -905,7 +884,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit); llvm::DIType InhTag = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_inheritance, - Unit, "", llvm::DICompileUnit(), 0, 0, 0, + Unit, "", Unit, 0, 0, 0, 0 /* offset */, 0, SClassTy); EltTys.push_back(InhTag); } @@ -926,7 +905,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, // Get the location for the field. SourceLocation FieldDefLoc = Field->getLocation(); - llvm::DICompileUnit FieldDefUnit = getOrCreateCompileUnit(FieldDefLoc); + llvm::DIFile FieldDefUnit = getOrCreateFile(FieldDefLoc); PresumedLoc PLoc = SM.getPresumedLoc(FieldDefLoc); unsigned FieldLine = PLoc.isInvalid() ? 0 : PLoc.getLine(); @@ -984,7 +963,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, } llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { EnumDecl *ED = Ty->getDecl(); llvm::SmallVector<llvm::DIDescriptor, 32> Enumerators; @@ -1002,7 +981,7 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty, DebugFactory.GetOrCreateArray(Enumerators.data(), Enumerators.size()); SourceLocation DefLoc = ED->getLocation(); - llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(DefLoc); + llvm::DIFile DefUnit = getOrCreateFile(DefLoc); SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(DefLoc); unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine(); @@ -1025,7 +1004,7 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty, } llvm::DIType CGDebugInfo::CreateType(const TagType *Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { if (const RecordType *RT = dyn_cast<RecordType>(Ty)) return CreateType(RT, Unit); else if (const EnumType *ET = dyn_cast<EnumType>(Ty)) @@ -1035,7 +1014,7 @@ llvm::DIType CGDebugInfo::CreateType(const TagType *Ty, } llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit); uint64_t NumElems = Ty->getNumElements(); if (NumElems > 0) @@ -1051,13 +1030,13 @@ llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_vector_type, - Unit, "", llvm::DICompileUnit(), + Unit, "", Unit, 0, Size, Align, 0, 0, ElementTy, SubscriptArray); } llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { uint64_t Size; uint64_t Align; @@ -1096,7 +1075,7 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIType DbgTy = DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type, - Unit, "", llvm::DICompileUnit(), + Unit, "", Unit, 0, Size, Align, 0, 0, getOrCreateType(EltTy, Unit), SubscriptArray); @@ -1104,13 +1083,13 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, } llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type, Ty, Ty->getPointeeType(), Unit); } llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty, - llvm::DICompileUnit U) { + llvm::DIFile U) { QualType PointerDiffTy = CGM.getContext().getPointerDiffType(); llvm::DIType PointerDiffDITy = getOrCreateType(PointerDiffTy, U); @@ -1129,14 +1108,14 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty, // FIXME: This should probably be a function type instead. ElementTypes[0] = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, U, - "ptr", llvm::DICompileUnit(), 0, + "ptr", U, 0, Info.first, Info.second, FieldOffset, 0, PointerDiffDITy); FieldOffset += Info.first; ElementTypes[1] = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, U, - "ptr", llvm::DICompileUnit(), 0, + "ptr", U, 0, Info.first, Info.second, FieldOffset, 0, PointerDiffDITy); @@ -1146,7 +1125,7 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty, return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type, U, llvm::StringRef("test"), - llvm::DICompileUnit(), 0, FieldOffset, + U, 0, FieldOffset, 0, 0, 0, llvm::DIType(), Elements); } @@ -1192,7 +1171,7 @@ static QualType UnwrapTypeForDebugInfo(QualType T) { /// getOrCreateType - Get the type from the cache or create a new /// one if necessary. llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { if (Ty.isNull()) return llvm::DIType(); @@ -1218,7 +1197,7 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, /// CreateTypeNode - Create a new debug type node. llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, - llvm::DICompileUnit Unit) { + llvm::DIFile Unit) { // Handle qualifiers, which recursively handles what they refer to. if (Ty.hasLocalQualifiers()) return CreateQualifiedType(Ty, Unit); @@ -1267,6 +1246,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, case Type::MemberPointer: return CreateType(cast<MemberPointerType>(Ty), Unit); + case Type::InjectedClassName: case Type::TemplateSpecialization: case Type::Elaborated: case Type::QualifiedName: @@ -1306,8 +1286,8 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator FI = SPCache.find(FD); if (FI != SPCache.end()) { - llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(FI->second)); - if (!SP.isNull() && SP.isSubprogram() && SP.isDefinition()) { + llvm::DIDescriptor SP(dyn_cast_or_null<llvm::MDNode>(FI->second)); + if (SP.isSubprogram() && llvm::DISubprogram(SP.getNode()).isDefinition()) { RegionStack.push_back(SP.getNode()); RegionMap[D] = llvm::WeakVH(SP.getNode()); return; @@ -1329,7 +1309,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, // It is expected that CurLoc is set before using EmitFunctionStart. // Usually, CurLoc points to the left bracket location of compound // statement representing function body. - llvm::DICompileUnit Unit = getOrCreateCompileUnit(CurLoc); + llvm::DIFile Unit = getOrCreateFile(CurLoc); SourceManager &SM = CGM.getContext().getSourceManager(); unsigned LineNo = SM.getPresumedLoc(CurLoc).getLine(); @@ -1359,7 +1339,7 @@ void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) { PrevLoc = CurLoc; // Get the appropriate compile unit. - llvm::DICompileUnit Unit = getOrCreateCompileUnit(CurLoc); + llvm::DIFile Unit = getOrCreateFile(CurLoc); PresumedLoc PLoc = SM.getPresumedLoc(CurLoc); llvm::DIDescriptor DR(RegionStack.back()); @@ -1406,7 +1386,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, uint64_t FieldSize, FieldOffset; unsigned FieldAlign; - llvm::DICompileUnit Unit = getOrCreateCompileUnit(VD->getLocation()); + llvm::DIFile Unit = getOrCreateFile(VD->getLocation()); QualType Type = VD->getType(); FieldOffset = 0; @@ -1415,7 +1395,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "__isa", llvm::DICompileUnit(), + "__isa", Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -1426,7 +1406,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "__forwarding", llvm::DICompileUnit(), + "__forwarding", Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -1437,7 +1417,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "__flags", llvm::DICompileUnit(), + "__flags", Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -1448,7 +1428,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "__size", llvm::DICompileUnit(), + "__size", Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -1461,8 +1441,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "__copy_helper", - llvm::DICompileUnit(), + "__copy_helper", Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -1473,8 +1452,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "__destroy_helper", - llvm::DICompileUnit(), + "__destroy_helper", Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -1497,7 +1475,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, - Unit, "", llvm::DICompileUnit(), + Unit, "", Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -1512,7 +1490,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, *XOffset = FieldOffset; FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - VD->getName(), llvm::DICompileUnit(), + VD->getName(), Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -1524,8 +1502,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, unsigned Flags = llvm::DIType::FlagBlockByrefStruct; return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type, - Unit, "", - llvm::DICompileUnit(), + Unit, "", Unit, 0, FieldOffset, 0, 0, Flags, llvm::DIType(), Elements); @@ -1542,7 +1519,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, if (CGO.OptimizationLevel) return; - llvm::DICompileUnit Unit = getOrCreateCompileUnit(VD->getLocation()); + llvm::DIFile Unit = getOrCreateFile(VD->getLocation()); llvm::DIType Ty; uint64_t XOffset = 0; if (VD->hasAttr<BlocksAttr>()) @@ -1560,9 +1537,9 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, if (PLoc.isValid()) { Line = PLoc.getLine(); Column = PLoc.getColumn(); - Unit = getOrCreateCompileUnit(CurLoc); + Unit = getOrCreateFile(CurLoc); } else { - Unit = llvm::DICompileUnit(); + Unit = llvm::DIFile(); } // Create the descriptor for the variable. @@ -1596,7 +1573,7 @@ void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag, return; uint64_t XOffset = 0; - llvm::DICompileUnit Unit = getOrCreateCompileUnit(VD->getLocation()); + llvm::DIFile Unit = getOrCreateFile(VD->getLocation()); llvm::DIType Ty; if (VD->hasAttr<BlocksAttr>()) Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset); @@ -1610,7 +1587,7 @@ void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag, if (!PLoc.isInvalid()) Line = PLoc.getLine(); else - Unit = llvm::DICompileUnit(); + Unit = llvm::DIFile(); CharUnits offset = CGF->BlockDecls[VD]; llvm::SmallVector<llvm::Value *, 9> addr; @@ -1675,7 +1652,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, const VarDecl *D) { // Create global variable debug descriptor. - llvm::DICompileUnit Unit = getOrCreateCompileUnit(D->getLocation()); + llvm::DIFile Unit = getOrCreateFile(D->getLocation()); SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(D->getLocation()); unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine(); @@ -1706,7 +1683,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, ObjCInterfaceDecl *ID) { // Create global variable debug descriptor. - llvm::DICompileUnit Unit = getOrCreateCompileUnit(ID->getLocation()); + llvm::DIFile Unit = getOrCreateFile(ID->getLocation()); SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(ID->getLocation()); unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine(); @@ -1750,7 +1727,7 @@ CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl, getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()), Unit); llvm::DINameSpace NS = DebugFactory.CreateNameSpace(Context, NSDecl->getName(), - llvm::DICompileUnit(Unit.getNode()), LineNo); + llvm::DIFile(Unit.getNode()), LineNo); NameSpaceCache[NSDecl] = llvm::WeakVH(NS.getNode()); return NS; } diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 50f575940886..47a462048342 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -43,16 +43,14 @@ namespace CodeGen { /// the backend. class CGDebugInfo { CodeGenModule &CGM; - bool isMainCompileUnitCreated; llvm::DIFactory DebugFactory; - + llvm::DICompileUnit TheCU; SourceLocation CurLoc, PrevLoc; - llvm::DIType VTablePtrType; - - /// CompileUnitCache - Cache of previously constructed CompileUnits. - llvm::DenseMap<unsigned, llvm::DICompileUnit> CompileUnitCache; - + /// FwdDeclCount - This counter is used to ensure unique names for forward + /// record decls. + unsigned FwdDeclCount; + /// TypeCache - Cache of previously constructed Types. // FIXME: Eliminate this map. Be careful of iterator invalidation. std::map<void *, llvm::WeakVH> TypeCache; @@ -71,52 +69,52 @@ class CGDebugInfo { llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH> NameSpaceCache; /// Helper functions for getOrCreateType. - llvm::DIType CreateType(const BuiltinType *Ty, llvm::DICompileUnit U); - llvm::DIType CreateType(const ComplexType *Ty, llvm::DICompileUnit U); - llvm::DIType CreateQualifiedType(QualType Ty, llvm::DICompileUnit U); - llvm::DIType CreateType(const TypedefType *Ty, llvm::DICompileUnit U); + llvm::DIType CreateType(const BuiltinType *Ty, llvm::DIFile F); + llvm::DIType CreateType(const ComplexType *Ty, llvm::DIFile F); + llvm::DIType CreateQualifiedType(QualType Ty, llvm::DIFile F); + llvm::DIType CreateType(const TypedefType *Ty, llvm::DIFile F); llvm::DIType CreateType(const ObjCObjectPointerType *Ty, - llvm::DICompileUnit Unit); - llvm::DIType CreateType(const PointerType *Ty, llvm::DICompileUnit U); - llvm::DIType CreateType(const BlockPointerType *Ty, llvm::DICompileUnit U); - llvm::DIType CreateType(const FunctionType *Ty, llvm::DICompileUnit U); - llvm::DIType CreateType(const TagType *Ty, llvm::DICompileUnit U); - llvm::DIType CreateType(const RecordType *Ty, llvm::DICompileUnit U); - llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DICompileUnit U); - llvm::DIType CreateType(const EnumType *Ty, llvm::DICompileUnit U); - llvm::DIType CreateType(const VectorType *Ty, llvm::DICompileUnit Unit); - llvm::DIType CreateType(const ArrayType *Ty, llvm::DICompileUnit U); - llvm::DIType CreateType(const LValueReferenceType *Ty, llvm::DICompileUnit U); - llvm::DIType CreateType(const MemberPointerType *Ty, llvm::DICompileUnit U); + llvm::DIFile F); + llvm::DIType CreateType(const PointerType *Ty, llvm::DIFile F); + llvm::DIType CreateType(const BlockPointerType *Ty, llvm::DIFile F); + llvm::DIType CreateType(const FunctionType *Ty, llvm::DIFile F); + llvm::DIType CreateType(const TagType *Ty, llvm::DIFile F); + llvm::DIType CreateType(const RecordType *Ty, llvm::DIFile F); + llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F); + llvm::DIType CreateType(const EnumType *Ty, llvm::DIFile F); + llvm::DIType CreateType(const VectorType *Ty, llvm::DIFile F); + llvm::DIType CreateType(const ArrayType *Ty, llvm::DIFile F); + llvm::DIType CreateType(const LValueReferenceType *Ty, llvm::DIFile F); + llvm::DIType CreateType(const MemberPointerType *Ty, llvm::DIFile F); llvm::DIType getOrCreateMethodType(const CXXMethodDecl *Method, - llvm::DICompileUnit Unit); - llvm::DIType getOrCreateVTablePtrType(llvm::DICompileUnit Unit); + llvm::DIFile F); + llvm::DIType getOrCreateVTablePtrType(llvm::DIFile F); llvm::DINameSpace getOrCreateNameSpace(const NamespaceDecl *N, llvm::DIDescriptor Unit); llvm::DIType CreatePointerLikeType(unsigned Tag, const Type *Ty, QualType PointeeTy, - llvm::DICompileUnit U); + llvm::DIFile F); llvm::DISubprogram CreateCXXMemberFunction(const CXXMethodDecl *Method, - llvm::DICompileUnit Unit, + llvm::DIFile F, llvm::DICompositeType &RecordTy); void CollectCXXMemberFunctions(const CXXRecordDecl *Decl, - llvm::DICompileUnit U, + llvm::DIFile F, llvm::SmallVectorImpl<llvm::DIDescriptor> &E, llvm::DICompositeType &T); void CollectCXXBases(const CXXRecordDecl *Decl, - llvm::DICompileUnit Unit, + llvm::DIFile F, llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys, llvm::DICompositeType &RecordTy); - void CollectRecordFields(const RecordDecl *Decl, llvm::DICompileUnit U, + void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile F, llvm::SmallVectorImpl<llvm::DIDescriptor> &E); void CollectVtableInfo(const CXXRecordDecl *Decl, - llvm::DICompileUnit Unit, + llvm::DIFile F, llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys); public: @@ -185,16 +183,19 @@ private: llvm::DIDescriptor getContextDescriptor(const Decl *Decl, llvm::DIDescriptor &CU); - /// getOrCreateCompileUnit - Get the compile unit from the cache or create a - /// new one if necessary. - llvm::DICompileUnit getOrCreateCompileUnit(SourceLocation Loc); + /// CreateCompileUnit - Create new compile unit. + void CreateCompileUnit(); + + /// getOrCreateFile - Get the file debug info descriptor for the input + /// location. + llvm::DIFile getOrCreateFile(SourceLocation Loc); /// getOrCreateType - Get the type from the cache or create a new type if /// necessary. - llvm::DIType getOrCreateType(QualType Ty, llvm::DICompileUnit Unit); + llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile F); /// CreateTypeNode - Create type metadata for a source language type. - llvm::DIType CreateTypeNode(QualType Ty, llvm::DICompileUnit Unit); + llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile F); /// getFunctionName - Get function name for the given FunctionDecl. If the /// name is constructred on demand (e.g. C++ destructor) then the name diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index ac189a064904..4847ca3f8248 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -178,6 +178,11 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore) { //===----------------------------------------------------------------------===// void AggExprEmitter::VisitCastExpr(CastExpr *E) { + if (!DestPtr) { + Visit(E->getSubExpr()); + return; + } + switch (E->getCastKind()) { default: assert(0 && "Unhandled cast kind!"); @@ -205,6 +210,11 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { break; case CastExpr::CK_NullToMemberPointer: { + // If the subexpression's type is the C++0x nullptr_t, emit the + // subexpression, which may have side effects. + if (E->getSubExpr()->getType()->isNullPtrType()) + Visit(E->getSubExpr()); + const llvm::Type *PtrDiffTy = CGF.ConvertType(CGF.getContext().getPointerDiffType()); @@ -652,6 +662,16 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { return; } + + // If we're initializing the whole aggregate, just do it in place. + // FIXME: This is a hack around an AST bug (PR6537). + if (NumInitElements == 1 && E->getType() == E->getInit(0)->getType()) { + EmitInitializationToLValue(E->getInit(0), + LValue::MakeAddr(DestPtr, Qualifiers()), + E->getType()); + return; + } + // Here we iterate over the fields; this makes it simpler to both // default-initialize fields and skip over unnamed fields. @@ -670,8 +690,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { // We never generate write-barries for initialized fields. LValue::SetObjCNonGC(FieldLoc, true); if (CurInitVal < NumInitElements) { - // Store the initializer into the field - EmitInitializationToLValue(E->getInit(CurInitVal++), FieldLoc, + // Store the initializer into the field. + EmitInitializationToLValue(E->getInit(CurInitVal++), FieldLoc, Field->getType()); } else { // We're out of initalizers; default-initialize to null diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index b62e6ed44366..3ff77f0170c1 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -59,7 +59,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { // Find the receiver llvm::Value *Receiver; if (!ReceiverExpr) { - const ObjCInterfaceDecl *OID = E->getClassInfo().first; + const ObjCInterfaceDecl *OID = E->getClassInfo().Decl; // Very special case, super send in class method. The receiver is // self (the class object) and the send uses super semantics. diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 932bd079e93f..4500ec033cd8 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -60,10 +60,13 @@ public: /// Method - The method decl of the overrider. const CXXMethodDecl *Method; - /// Offset - the base offset of the overrider relative to the layout class. - int64_t Offset; + /// Offset - the base offset of the overrider in the layout class. + uint64_t Offset; - OverriderInfo() : Method(0), Offset(0) { } + /// OldOffset - FIXME: Remove this. + int64_t OldOffset; + + OverriderInfo() : Method(0), Offset(0), OldOffset(0) { } }; private: @@ -71,6 +74,16 @@ private: /// are stored. const CXXRecordDecl *MostDerivedClass; + /// MostDerivedClassOffset - If we're building final overriders for a + /// construction vtable, this holds the offset from the layout class to the + /// most derived class. + const uint64_t MostDerivedClassOffset; + + /// LayoutClass - The class we're using for layout information. Will be + /// different than the most derived class if the final overriders are for a + /// construction vtable. + const CXXRecordDecl *LayoutClass; + ASTContext &Context; /// MostDerivedClassLayout - the AST record layout of the most derived class. @@ -122,11 +135,13 @@ private: /// subobject (and all its direct and indirect bases). void ComputeFinalOverriders(BaseSubobject Base, bool BaseSubobjectIsVisitedVBase, + uint64_t OffsetInLayoutClass, SubobjectOffsetsMapTy &Offsets); /// AddOverriders - Add the final overriders for this base subobject to the /// map of final overriders. - void AddOverriders(BaseSubobject Base, SubobjectOffsetsMapTy &Offsets); + void AddOverriders(BaseSubobject Base,uint64_t OffsetInLayoutClass, + SubobjectOffsetsMapTy &Offsets); /// PropagateOverrider - Propagate the NewMD overrider to all the functions /// that OldMD overrides. For example, if we have: @@ -139,6 +154,7 @@ private: /// C::f. void PropagateOverrider(const CXXMethodDecl *OldMD, BaseSubobject NewBase, + uint64_t OverriderOffsetInLayoutClass, const CXXMethodDecl *NewMD, SubobjectOffsetsMapTy &Offsets); @@ -146,7 +162,9 @@ private: SubobjectOffsetsMapTy &Offsets); public: - explicit FinalOverriders(const CXXRecordDecl *MostDerivedClass); + FinalOverriders(const CXXRecordDecl *MostDerivedClass, + uint64_t MostDerivedClassOffset, + const CXXRecordDecl *LayoutClass); /// getOverrider - Get the final overrider for the given method declaration in /// the given base subobject. @@ -181,15 +199,19 @@ public: #define DUMP_OVERRIDERS 0 -FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass) +FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass, + uint64_t MostDerivedClassOffset, + const CXXRecordDecl *LayoutClass) : MostDerivedClass(MostDerivedClass), + MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()), MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) { // Compute the final overriders. SubobjectOffsetsMapTy Offsets; ComputeFinalOverriders(BaseSubobject(MostDerivedClass, 0), - /*BaseSubobjectIsVisitedVBase=*/false, Offsets); + /*BaseSubobjectIsVisitedVBase=*/false, + MostDerivedClassOffset, Offsets); VisitedVirtualBases.clear(); #if DUMP_OVERRIDERS @@ -199,18 +221,19 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass) // Also dump the base offsets (for now). for (SubobjectOffsetsMapTy::const_iterator I = Offsets.begin(), E = Offsets.end(); I != E; ++I) { - const OffsetVectorTy& OffsetVector = I->second; + const OffsetSetVectorTy& OffsetSetVector = I->second; llvm::errs() << "Base offsets for "; llvm::errs() << I->first->getQualifiedNameAsString() << '\n'; - for (unsigned I = 0, E = OffsetVector.size(); I != E; ++I) - llvm::errs() << " " << I << " - " << OffsetVector[I] << '\n'; + for (unsigned I = 0, E = OffsetSetVector.size(); I != E; ++I) + llvm::errs() << " " << I << " - " << OffsetSetVector[I] / 8 << '\n'; } #endif } void FinalOverriders::AddOverriders(BaseSubobject Base, + uint64_t OffsetInLayoutClass, SubobjectOffsetsMapTy &Offsets) { const CXXRecordDecl *RD = Base.getBase(); @@ -222,13 +245,14 @@ void FinalOverriders::AddOverriders(BaseSubobject Base, continue; // First, propagate the overrider. - PropagateOverrider(MD, Base, MD, Offsets); + PropagateOverrider(MD, Base, OffsetInLayoutClass, MD, Offsets); // Add the overrider as the final overrider of itself. OverriderInfo& Overrider = OverridersMap[std::make_pair(Base, MD)]; assert(!Overrider.Method && "Overrider should not exist yet!"); - Overrider.Offset = Base.getBaseOffset(); + Overrider.OldOffset = Base.getBaseOffset(); + Overrider.Offset = OffsetInLayoutClass; Overrider.Method = MD; } } @@ -346,6 +370,7 @@ ComputeReturnAdjustmentBaseOffset(ASTContext &Context, void FinalOverriders::PropagateOverrider(const CXXMethodDecl *OldMD, BaseSubobject NewBase, + uint64_t OverriderOffsetInLayoutClass, const CXXMethodDecl *NewMD, SubobjectOffsetsMapTy &Offsets) { for (CXXMethodDecl::method_iterator I = OldMD->begin_overridden_methods(), @@ -389,11 +414,13 @@ void FinalOverriders::PropagateOverrider(const CXXMethodDecl *OldMD, } // Set the new overrider. - Overrider.Offset = NewBase.getBaseOffset(); + Overrider.Offset = OverriderOffsetInLayoutClass; + Overrider.OldOffset = NewBase.getBaseOffset(); Overrider.Method = NewMD; // And propagate it further. - PropagateOverrider(OverriddenMD, NewBase, NewMD, Offsets); + PropagateOverrider(OverriddenMD, NewBase, OverriderOffsetInLayoutClass, + NewMD, Offsets); } } } @@ -416,6 +443,7 @@ FinalOverriders::MergeSubobjectOffsets(const SubobjectOffsetsMapTy &NewOffsets, void FinalOverriders::ComputeFinalOverriders(BaseSubobject Base, bool BaseSubobjectIsVisitedVBase, + uint64_t OffsetInLayoutClass, SubobjectOffsetsMapTy &Offsets) { const CXXRecordDecl *RD = Base.getBase(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); @@ -433,12 +461,20 @@ void FinalOverriders::ComputeFinalOverriders(BaseSubobject Base, bool IsVisitedVirtualBase = BaseSubobjectIsVisitedVBase; uint64_t BaseOffset; + uint64_t BaseOffsetInLayoutClass; if (I->isVirtual()) { if (!VisitedVirtualBases.insert(BaseDecl)) IsVisitedVirtualBase = true; BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); + + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); + BaseOffsetInLayoutClass = + LayoutClassLayout.getVBaseClassOffset(BaseDecl); } else { BaseOffset = Layout.getBaseClassOffset(BaseDecl) + Base.getBaseOffset(); + BaseOffsetInLayoutClass = Layout.getBaseClassOffset(BaseDecl) + + OffsetInLayoutClass; } // Compute the final overriders for this base. @@ -463,13 +499,14 @@ void FinalOverriders::ComputeFinalOverriders(BaseSubobject Base, // Here, we still want to compute the overriders for A as a base of C, // because otherwise we'll miss that C::g overrides A::f. ComputeFinalOverriders(BaseSubobject(BaseDecl, BaseOffset), - IsVisitedVirtualBase, NewOffsets); + IsVisitedVirtualBase, BaseOffsetInLayoutClass, + NewOffsets); } /// Now add the overriders for this particular subobject. /// (We don't want to do this more than once for a virtual base). if (!BaseSubobjectIsVisitedVBase) - AddOverriders(Base, NewOffsets); + AddOverriders(Base, OffsetInLayoutClass, NewOffsets); // And merge the newly discovered subobject offsets. MergeSubobjectOffsets(NewOffsets, Offsets); @@ -508,7 +545,7 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) { } Out << "Final overriders for (" << RD->getQualifiedNameAsString() << ", "; - Out << Base.getBaseOffset() << ")\n"; + Out << Base.getBaseOffset() / 8 << ")\n"; // Now dump the overriders for this base subobject. for (CXXRecordDecl::method_iterator I = RD->method_begin(), @@ -522,7 +559,7 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) { Out << " " << MD->getQualifiedNameAsString() << " - ("; Out << Overrider.Method->getQualifiedNameAsString(); - Out << ", " << Overrider.Offset << ')'; + Out << ", " << Overrider.OldOffset / 8 << ", " << Overrider.Offset / 8 << ')'; AdjustmentOffsetsMapTy::const_iterator AI = ReturnAdjustments.find(std::make_pair(Base, MD)); @@ -1173,15 +1210,17 @@ private: /// thunk. Since we require that a call to C::f() first convert to A*, /// C-in-D's copy of A's vtable is never referenced, so this is not /// necessary. - bool IsOverriderUsed(BaseSubobject Base, - BaseSubobject FirstBaseInPrimaryBaseChain, - uint64_t OffsetInLayoutClass, - FinalOverriders::OverriderInfo Overrider) const; + bool IsOverriderUsed(const CXXMethodDecl *Overrider, + uint64_t BaseOffsetInLayoutClass, + const CXXRecordDecl *FirstBaseInPrimaryBaseChain, + uint64_t FirstBaseOffsetInLayoutClass) const; + /// AddMethods - Add the methods of this base subobject and all its /// primary bases to the vtable components vector. - void AddMethods(BaseSubobject Base, BaseSubobject FirstBaseInPrimaryBaseChain, - uint64_t OffsetInLayoutClass, + void AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass, + const CXXRecordDecl *FirstBaseInPrimaryBaseChain, + uint64_t FirstBaseOffsetInLayoutClass, PrimaryBasesSetVectorTy &PrimaryBases); // LayoutVtable - Layout the vtable for the given base class, including its @@ -1201,6 +1240,7 @@ private: /// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this /// class hierarchy. void DeterminePrimaryVirtualBases(const CXXRecordDecl *RD, + uint64_t OffsetInLayoutClass, VisitedVirtualBasesSetTy &VBases); /// LayoutVtablesForVirtualBases - Layout vtables for all virtual bases of the @@ -1222,7 +1262,7 @@ public: MostDerivedClassOffset(MostDerivedClassOffset), MostDerivedClassIsVirtual(MostDerivedClassIsVirtual), LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()), - Overriders(MostDerivedClass) { + Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) { LayoutVtable(); } @@ -1269,7 +1309,7 @@ void VtableBuilder::ComputeThisAdjustments() { Overriders.getOverrider(OverriddenBaseSubobject, MD); // Check if we need an adjustment. - if (Overrider.Offset == (int64_t)MethodInfo.BaseOffset) + if (Overrider.OldOffset == (int64_t)MethodInfo.BaseOffset) continue; uint64_t VtableIndex = MethodInfo.VtableIndex; @@ -1284,7 +1324,7 @@ void VtableBuilder::ComputeThisAdjustments() { continue; BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(), - Overrider.Offset); + Overrider.OldOffset); // Compute the adjustment offset. BaseOffset ThisAdjustmentOffset = @@ -1473,13 +1513,13 @@ OverridesIndirectMethodInBases(const CXXMethodDecl *MD, } bool -VtableBuilder::IsOverriderUsed(BaseSubobject Base, - BaseSubobject FirstBaseInPrimaryBaseChain, - uint64_t OffsetInLayoutClass, - FinalOverriders::OverriderInfo Overrider) const { +VtableBuilder::IsOverriderUsed(const CXXMethodDecl *Overrider, + uint64_t BaseOffsetInLayoutClass, + const CXXRecordDecl *FirstBaseInPrimaryBaseChain, + uint64_t FirstBaseOffsetInLayoutClass) const { // If the base and the first base in the primary base chain have the same // offsets, then this overrider will be used. - if (Base.getBaseOffset() == OffsetInLayoutClass) + if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass) return true; // We know now that Base (or a direct or indirect base of it) is a primary @@ -1488,12 +1528,12 @@ VtableBuilder::IsOverriderUsed(BaseSubobject Base, // If the overrider is the first base in the primary base chain, we know // that the overrider will be used. - if (Overrider.Method->getParent() == FirstBaseInPrimaryBaseChain.getBase()) + if (Overrider->getParent() == FirstBaseInPrimaryBaseChain) return true; VtableBuilder::PrimaryBasesSetVectorTy PrimaryBases; - const CXXRecordDecl *RD = FirstBaseInPrimaryBaseChain.getBase(); + const CXXRecordDecl *RD = FirstBaseInPrimaryBaseChain; PrimaryBases.insert(RD); // Now traverse the base chain, starting with the first base, until we find @@ -1515,7 +1555,7 @@ VtableBuilder::IsOverriderUsed(BaseSubobject Base, // Now check if this is the primary base that is not a primary base in the // most derived class. if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) != - OffsetInLayoutClass) { + FirstBaseOffsetInLayoutClass) { // We found it, stop walking the chain. break; } @@ -1532,7 +1572,7 @@ VtableBuilder::IsOverriderUsed(BaseSubobject Base, // If the final overrider is an override of one of the primary bases, // then we know that it will be used. - return OverridesIndirectMethodInBases(Overrider.Method, PrimaryBases); + return OverridesIndirectMethodInBases(Overrider, PrimaryBases); } /// FindNearestOverriddenMethod - Given a method, returns the overridden method @@ -1557,17 +1597,17 @@ FindNearestOverriddenMethod(const CXXMethodDecl *MD, return 0; } -void -VtableBuilder::AddMethods(BaseSubobject Base, - BaseSubobject FirstBaseInPrimaryBaseChain, - uint64_t OffsetInLayoutClass, +void +VtableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass, + const CXXRecordDecl *FirstBaseInPrimaryBaseChain, + uint64_t FirstBaseOffsetInLayoutClass, PrimaryBasesSetVectorTy &PrimaryBases) { const CXXRecordDecl *RD = Base.getBase(); - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) { - uint64_t BaseOffset; + uint64_t PrimaryBaseOffset; + uint64_t PrimaryBaseOffsetInLayoutClass; if (Layout.getPrimaryBaseWasVirtual()) { assert(Layout.getVBaseClassOffset(PrimaryBase) == 0 && "Primary vbase should have a zero offset!"); @@ -1575,17 +1615,25 @@ VtableBuilder::AddMethods(BaseSubobject Base, const ASTRecordLayout &MostDerivedClassLayout = Context.getASTRecordLayout(MostDerivedClass); - BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase); + PrimaryBaseOffset = + MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase); + + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); + + PrimaryBaseOffsetInLayoutClass = + LayoutClassLayout.getVBaseClassOffset(PrimaryBase); } else { assert(Layout.getBaseClassOffset(PrimaryBase) == 0 && "Primary base should have a zero offset!"); - BaseOffset = Base.getBaseOffset(); + PrimaryBaseOffset = Base.getBaseOffset(); + PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass; } - // FIXME: OffsetInLayoutClass is not right here. - AddMethods(BaseSubobject(PrimaryBase, BaseOffset), - FirstBaseInPrimaryBaseChain, OffsetInLayoutClass, PrimaryBases); + AddMethods(BaseSubobject(PrimaryBase, PrimaryBaseOffset), + PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain, + FirstBaseOffsetInLayoutClass, PrimaryBases); if (!PrimaryBases.insert(PrimaryBase)) assert(false && "Found a duplicate primary base!"); @@ -1636,9 +1684,10 @@ VtableBuilder::AddMethods(BaseSubobject Base, MethodInfoMap.insert(std::make_pair(MD, MethodInfo)); // Check if this overrider is going to be used. - if (!IsOverriderUsed(Base, FirstBaseInPrimaryBaseChain, OffsetInLayoutClass, - Overrider)) { - const CXXMethodDecl *OverriderMD = Overrider.Method; + const CXXMethodDecl *OverriderMD = Overrider.Method; + if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass, + FirstBaseInPrimaryBaseChain, + FirstBaseOffsetInLayoutClass)) { Components.push_back(VtableComponent::MakeUnusedFunction(OverriderMD)); continue; } @@ -1662,7 +1711,8 @@ void VtableBuilder::LayoutVtable() { VisitedVirtualBasesSetTy VBases; // Determine the primary virtual bases. - DeterminePrimaryVirtualBases(MostDerivedClass, VBases); + DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset, + VBases); VBases.clear(); LayoutVtablesForVirtualBases(MostDerivedClass, VBases); @@ -1700,7 +1750,8 @@ VtableBuilder::LayoutPrimaryAndSecondaryVtables(BaseSubobject Base, // Now go through all virtual member functions and add them. PrimaryBasesSetVectorTy PrimaryBases; - AddMethods(Base, Base, OffsetInLayoutClass, PrimaryBases); + AddMethods(Base, OffsetInLayoutClass, Base.getBase(), OffsetInLayoutClass, + PrimaryBases); // Compute 'this' pointer adjustments. ComputeThisAdjustments(); @@ -1771,7 +1822,8 @@ void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base, } void -VtableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD, +VtableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD, + uint64_t OffsetInLayoutClass, VisitedVirtualBasesSetTy &VBases) { const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); @@ -1785,8 +1837,15 @@ VtableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD, if (isBuildingConstructorVtable()) { // Check if the base is actually a primary base in the class we use for // layout. - // FIXME: Is this check enough? - if (MostDerivedClassOffset != 0) + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); + + uint64_t PrimaryBaseOffsetInLayoutClass = + LayoutClassLayout.getVBaseClassOffset(PrimaryBase); + + // We know that the base is not a primary base in the layout class if + // the base offsets are different. + if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass) IsPrimaryVirtualBase = false; } @@ -1801,10 +1860,22 @@ VtableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD, const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - if (I->isVirtual() && !VBases.insert(BaseDecl)) - continue; + uint64_t BaseOffsetInLayoutClass; + + if (I->isVirtual()) { + if (!VBases.insert(BaseDecl)) + continue; + + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); - DeterminePrimaryVirtualBases(BaseDecl, VBases); + BaseOffsetInLayoutClass = LayoutClassLayout.getVBaseClassOffset(BaseDecl); + } else { + BaseOffsetInLayoutClass = + OffsetInLayoutClass + Layout.getBaseClassOffset(BaseDecl); + } + + DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases); } } @@ -3405,7 +3476,22 @@ void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage, Vtable = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0, /*IsVirtual=*/false, AddressPoints); - GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD); + GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD); + + for (CXXRecordDecl::method_iterator i = RD->method_begin(), + e = RD->method_end(); i != e; ++i) { + if (!(*i)->isVirtual()) + continue; + if(!(*i)->hasInlineBody() && !(*i)->isImplicit()) + continue; + + if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) { + CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete)); + CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting)); + } else { + CGM.BuildThunksForVirtual(GlobalDecl(*i)); + } + } } llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) { @@ -3438,19 +3524,12 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) { return; } - // Emit the data. - GenerateClassData(CGM.getVtableLinkage(RD), RD); + if (Vtables.count(RD)) + return; - for (CXXRecordDecl::method_iterator i = RD->method_begin(), - e = RD->method_end(); i != e; ++i) { - if ((*i)->isVirtual() && ((*i)->hasInlineBody() || (*i)->isImplicit())) { - if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) { - CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete)); - CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting)); - } else { - CGM.BuildThunksForVirtual(GlobalDecl(*i)); - } - } - } + TemplateSpecializationKind kind = RD->getTemplateSpecializationKind(); + if (kind == TSK_ImplicitInstantiation) + CGM.DeferredVtables.push_back(RD); + else + GenerateClassData(CGM.getVtableLinkage(RD), RD); } - diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h index 6ccb011985fd..57220d9d5af5 100644 --- a/lib/CodeGen/CGVtable.h +++ b/lib/CodeGen/CGVtable.h @@ -173,15 +173,7 @@ private: uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD); void ComputeMethodVtableIndices(const CXXRecordDecl *RD); - - /// GenerateClassData - Generate all the class data requires to be generated - /// upon definition of a KeyFunction. This includes the vtable, the - /// rtti data structure and the VTT. - /// - /// \param Linkage - The desired linkage of the vtable, the RTTI and the VTT. - void GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage, - const CXXRecordDecl *RD); - + llvm::GlobalVariable * GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage, bool GenerateDefinition, const CXXRecordDecl *LayoutClass, @@ -245,6 +237,14 @@ public: llvm::GlobalVariable *getVTT(const CXXRecordDecl *RD); void MaybeEmitVtable(GlobalDecl GD); + + /// GenerateClassData - Generate all the class data requires to be generated + /// upon definition of a KeyFunction. This includes the vtable, the + /// rtti data structure and the VTT. + /// + /// \param Linkage - The desired linkage of the vtable, the RTTI and the VTT. + void GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage, + const CXXRecordDecl *RD); }; } // end namespace CodeGen diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index d6a56dad0ba5..c67948d27f08 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -488,7 +488,15 @@ void CodeGenModule::EmitDeferred() { // Emit code for any potentially referenced deferred decls. Since a // previously unused static decl may become used during the generation of code // for a static function, iterate until no changes are made. - while (!DeferredDeclsToEmit.empty()) { + + while (!DeferredDeclsToEmit.empty() || !DeferredVtables.empty()) { + if (!DeferredVtables.empty()) { + const CXXRecordDecl *RD = DeferredVtables.back(); + DeferredVtables.pop_back(); + getVtableInfo().GenerateClassData(getVtableLinkage(RD), RD); + continue; + } + GlobalDecl D = DeferredDeclsToEmit.back(); DeferredDeclsToEmit.pop_back(); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index c86f8b45bcdd..40dc56388981 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -451,7 +451,9 @@ public: /// GetTargetTypeStoreSize - Return the store size, in character units, of /// the given LLVM type. CharUnits GetTargetTypeStoreSize(const llvm::Type *Ty) const; - + + std::vector<const CXXRecordDecl*> DeferredVtables; + private: /// UniqueMangledName - Unique a name by (if necessary) inserting it into the /// MangledNames string map. diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 20d54b34105d..2e0580f5e79b 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -214,12 +214,6 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl *D) { if (!getASTContext().getLangOptions().CPlusPlus) return false; - // No mangling in an "implicit extern C" header. - if (D->getLocation().isValid() && - getASTContext().getSourceManager(). - isInExternCSystemHeader(D->getLocation())) - return false; - // Variables at global scope with non-internal linkage are not mangled if (!FD) { const DeclContext *DC = D->getDeclContext(); diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp index 98b64f16635f..d8e086db98d1 100644 --- a/lib/Driver/HostInfo.cpp +++ b/lib/Driver/HostInfo.cpp @@ -164,7 +164,7 @@ class TCEHostInfo : public HostInfo { public: TCEHostInfo(const Driver &D, const llvm::Triple &Triple); - ~TCEHostInfo() {}; + ~TCEHostInfo() {} virtual bool useDriverDriver() const; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index de9bdcc18816..bc521008cf7c 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -929,7 +929,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Special case debug options to only pass -g to clang. This is // wrong. - if (Args.hasArg(options::OPT_g_Group)) + Args.ClaimAllArgs(options::OPT_g_Group); + Arg *Garg = Args.getLastArg(options::OPT_g_Group); + if (Garg && Garg != Args.getLastArg(options::OPT_g0)) CmdArgs.push_back("-g"); Args.AddLastArg(CmdArgs, options::OPT_nostdinc); diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp index 702c1d0025d9..c845d56f4ec1 100644 --- a/lib/Frontend/CacheTokens.cpp +++ b/lib/Frontend/CacheTokens.cpp @@ -64,7 +64,7 @@ public: PTHEntryKeyVariant(struct stat* statbuf, const char* path) : Path(path), Kind(IsDE), StatBuf(new struct stat(*statbuf)) {} - PTHEntryKeyVariant(const char* path) + explicit PTHEntryKeyVariant(const char* path) : Path(path), Kind(IsNoExist), StatBuf(0) {} bool isFile() const { return Kind == IsFE; } @@ -513,7 +513,7 @@ public: int result = StatSysCallCache::stat(path, buf); if (result != 0) // Failed 'stat'. - PM.insert(path, PTHEntry()); + PM.insert(PTHEntryKeyVariant(path), PTHEntry()); else if (S_ISDIR(buf->st_mode)) { // Only cache directories with absolute paths. if (!llvm::sys::Path(path).isAbsolute()) diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 1831ca532beb..25b804aba7fc 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -94,7 +94,7 @@ namespace { public: explicit BinaryDiagnosticSerializer(llvm::raw_ostream &OS) : OS(OS), SourceMgr(0) { } - + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, const DiagnosticInfo &Info); }; @@ -341,7 +341,7 @@ void CompilerInstance::addOutputFile(llvm::StringRef Path, OutputFiles.push_back(std::make_pair(Path, OS)); } -void CompilerInstance::ClearOutputFiles(bool EraseFiles) { +void CompilerInstance::clearOutputFiles(bool EraseFiles) { for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) { delete it->second; diff --git a/lib/Frontend/DeclXML.cpp b/lib/Frontend/DeclXML.cpp index d7470d92a946..8750b1efcab5 100644 --- a/lib/Frontend/DeclXML.cpp +++ b/lib/Frontend/DeclXML.cpp @@ -29,6 +29,14 @@ class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> { } } + void addFunctionBody(FunctionDecl* FD) { + if (FD->isThisDeclarationADefinition()) { + Doc.addSubNode("Body"); + Doc.PrintStmt(FD->getBody()); + Doc.toParent(); + } + } + void addSubNodes(RecordDecl* RD) { for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); i != e; ++i) { @@ -37,6 +45,15 @@ class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> { } } + void addSubNodes(CXXRecordDecl* RD) { + addSubNodes(cast<RecordDecl>(RD)); + for (CXXRecordDecl::method_iterator i = RD->method_begin(), + e = RD->method_end(); i != e; ++i) { + Visit(*i); + Doc.toParent(); + } + } + void addSubNodes(EnumDecl* ED) { for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(), e = ED->enumerator_end(); i != e; ++i) { @@ -115,6 +132,8 @@ public: #define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T); #define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T); +#define SUB_NODE_FN_BODY_XML addFunctionBody(T); + #include "clang/Frontend/DeclXML.def" }; @@ -122,13 +141,6 @@ public: //--------------------------------------------------------- void DocumentXML::writeDeclToXML(Decl *D) { DeclPrinter(*this).Visit(D); - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - if (Stmt *Body = FD->getBody()) { - addSubNode("Body"); - PrintStmt(Body); - toParent(); - } - } toParent(); } diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp index 478c33939cd7..de2b056dc7ce 100644 --- a/lib/Frontend/DependencyFile.cpp +++ b/lib/Frontend/DependencyFile.cpp @@ -74,8 +74,7 @@ void clang::AttachDependencyFileGen(Preprocessor &PP, return; } - assert(!PP.getPPCallbacks() && "Preprocessor callbacks already registered!"); - PP.setPPCallbacks(new DependencyFileCallback(&PP, OS, Opts)); + PP.addPPCallbacks(new DependencyFileCallback(&PP, OS, Opts)); } /// FileMatchesDepCriteria - Determine whether the given Filename should be diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index 96a68c931e1f..66df7a61917b 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -180,7 +180,7 @@ void FrontendAction::EndSourceFile() { // Cleanup the output streams, and erase the output files if we encountered // an error. - CI.ClearOutputFiles(/*EraseFiles=*/CI.getDiagnostics().getNumErrors()); + CI.clearOutputFiles(/*EraseFiles=*/CI.getDiagnostics().getNumErrors()); // Inform the diagnostic client we are done with this source file. CI.getDiagnosticClient().EndSourceFile(); diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 4f972f0baff3..cd749d221db6 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -436,7 +436,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) { break; } - AddPath("/usr/local/include", System, false, false, false); + AddPath("/usr/local/include", System, true, false, false); AddPath("/usr/include", System, false, false, false); } diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index a878df784005..267f4c158508 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -120,7 +120,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { PARSE_LANGOPT_IMPORTANT(OpenCL, diag::warn_pch_opencl); PARSE_LANGOPT_BENIGN(CatchUndefined); PARSE_LANGOPT_IMPORTANT(ElideConstructors, diag::warn_pch_elide_constructors); -#undef PARSE_LANGOPT_IRRELEVANT +#undef PARSE_LANGOPT_IMPORTANT #undef PARSE_LANGOPT_BENIGN return false; @@ -1089,13 +1089,13 @@ void PCHReader::ReadDefinedMacros() { // If there was no preprocessor block, do nothing. if (!MacroCursor.getBitStreamReader()) return; - + llvm::BitstreamCursor Cursor = MacroCursor; if (Cursor.EnterSubBlock(pch::PREPROCESSOR_BLOCK_ID)) { Error("malformed preprocessor block record in PCH file"); return; } - + RecordData Record; while (true) { unsigned Code = Cursor.ReadCode(); @@ -1104,7 +1104,7 @@ void PCHReader::ReadDefinedMacros() { Error("error at end of preprocessor block in PCH file"); return; } - + if (Code == llvm::bitc::ENTER_SUBBLOCK) { // No known subblocks, always skip them. Cursor.ReadSubBlockID(); @@ -1114,12 +1114,12 @@ void PCHReader::ReadDefinedMacros() { } continue; } - + if (Code == llvm::bitc::DEFINE_ABBREV) { Cursor.ReadAbbrevRecord(); continue; } - + // Read a record. const char *BlobStart; unsigned BlobLen; @@ -1127,7 +1127,7 @@ void PCHReader::ReadDefinedMacros() { switch (Cursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { default: // Default behavior: ignore. break; - + case pch::PP_MACRO_OBJECT_LIKE: case pch::PP_MACRO_FUNCTION_LIKE: DecodeIdentifierInfo(Record[0]); @@ -1339,7 +1339,7 @@ PCHReader::ReadPCHBlock() { } UnusedStaticFuncs.swap(Record); break; - + case pch::LOCALLY_SCOPED_EXTERNAL_DECLS: if (!LocallyScopedExternalDecls.empty()) { Error("duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file"); @@ -1385,7 +1385,7 @@ PCHReader::ReadPCHBlock() { break; case pch::STAT_CACHE: { - PCHStatCache *MyStatCache = + PCHStatCache *MyStatCache = new PCHStatCache((const unsigned char *)BlobStart + Record[0], (const unsigned char *)BlobStart, NumStatHits, NumStatMisses); @@ -1393,7 +1393,7 @@ PCHReader::ReadPCHBlock() { StatCache = MyStatCache; break; } - + case pch::EXT_VECTOR_DECLS: if (!ExtVectorDecls.empty()) { Error("duplicate EXT_VECTOR_DECLS record in PCH file"); @@ -1412,7 +1412,7 @@ PCHReader::ReadPCHBlock() { Comments = (SourceRange *)BlobStart; NumComments = BlobLen / sizeof(SourceRange); break; - + case pch::VERSION_CONTROL_BRANCH_REVISION: { const std::string &CurBranch = getClangFullRepositoryVersion(); llvm::StringRef PCHBranch(BlobStart, BlobLen); @@ -1561,7 +1561,7 @@ void PCHReader::InitializeContext(ASTContext &Ctx) { PP->getIdentifierTable().setExternalIdentifierLookup(this); PP->getHeaderSearchInfo().SetExternalLookup(this); PP->setExternalSource(this); - + // Load the translation unit declaration ReadDeclRecord(DeclOffsets[0], 0); @@ -2018,6 +2018,12 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm), Replacement); } + + case pch::TYPE_INJECTED_CLASS_NAME: { + CXXRecordDecl *D = cast<CXXRecordDecl>(GetDecl(Record[0])); + QualType TST = GetType(Record[1]); // probably derivable + return Context->getInjectedClassNameType(D, TST); + } } // Suppress a GCC warning return QualType(); @@ -2172,6 +2178,9 @@ void TypeLocReader::VisitTemplateSpecializationTypeLoc( void TypeLocReader::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) { TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } +void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { + TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} void TypeLocReader::VisitTypenameTypeLoc(TypenameTypeLoc TL) { TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } @@ -2271,7 +2280,7 @@ PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, case TemplateArgument::Type: return GetTypeSourceInfo(Record, Index); case TemplateArgument::Template: { - SourceLocation + SourceLocation QualStart = SourceLocation::getFromRawEncoding(Record[Index++]), QualEnd = SourceLocation::getFromRawEncoding(Record[Index++]), TemplateNameLoc = SourceLocation::getFromRawEncoding(Record[Index++]); @@ -2487,7 +2496,7 @@ void PCHReader::InitializeSema(Sema &S) { VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I])); SemaObj->TentativeDefinitions.push_back(Var); } - + // If there were any unused static functions, deserialize them and add to // Sema's list of unused static functions. for (unsigned I = 0, N = UnusedStaticFuncs.size(); I != N; ++I) { diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 356bd0726e52..a3f5eac480cd 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -211,6 +211,7 @@ void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]); MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); MD->setResultType(Reader.GetType(Record[Idx++])); + MD->setResultTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx)); MD->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); unsigned NumParams = Record[Idx++]; llvm::SmallVector<ParmVarDecl *, 16> Params; @@ -690,7 +691,7 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { break; case pch::DECL_OBJC_METHOD: D = ObjCMethodDecl::Create(*Context, SourceLocation(), SourceLocation(), - Selector(), QualType(), 0); + Selector(), QualType(), 0, 0); break; case pch::DECL_OBJC_INTERFACE: D = ObjCInterfaceDecl::Create(*Context, 0, SourceLocation(), 0); diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index d123694d699d..7b94805d3999 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -792,8 +792,9 @@ unsigned PCHStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) { cast_or_null<Expr>(StmtStack[StmtStack.size() - E->getNumArgs() - 1])); if (!E->getReceiver()) { ObjCMessageExpr::ClassInfo CI; - CI.first = cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])); - CI.second = Reader.GetIdentifierInfo(Record, Idx); + CI.Decl = cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])); + CI.Name = Reader.GetIdentifierInfo(Record, Idx); + CI.Loc = SourceLocation::getFromRawEncoding(Record[Idx++]); E->setClassInfo(CI); } diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 93af75468382..eed3cc1a5b3d 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -235,6 +235,12 @@ void PCHTypeWriter::VisitQualifiedNameType(const QualifiedNameType *T) { assert(false && "Cannot serialize qualified name types"); } +void PCHTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) { + Writer.AddDeclRef(T->getDecl(), Record); + Writer.AddTypeRef(T->getUnderlyingType(), Record); + Code = pch::TYPE_INJECTED_CLASS_NAME; +} + void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { Writer.AddDeclRef(T->getDecl(), Record); Record.push_back(T->getNumProtocols()); @@ -394,6 +400,9 @@ void TypeLocWriter::VisitTemplateSpecializationTypeLoc( void TypeLocWriter::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); } +void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { + Writer.AddSourceLocation(TL.getNameLoc(), Record); +} void TypeLocWriter::VisitTypenameTypeLoc(TypenameTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); } diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index e776d32454d2..0774797463e0 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -210,6 +210,7 @@ void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway Record.push_back(D->getObjCDeclQualifier()); Writer.AddTypeRef(D->getResultType(), Record); + Writer.AddTypeSourceInfo(D->getResultTypeSourceInfo(), Record); Writer.AddSourceLocation(D->getLocEnd(), Record); Record.push_back(D->param_size()); for (ObjCMethodDecl::param_iterator P = D->param_begin(), diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index a8cc9d6f4591..9a5417ca6102 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -720,8 +720,9 @@ void PCHStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) { if (!E->getReceiver()) { ObjCMessageExpr::ClassInfo CI = E->getClassInfo(); - Writer.AddDeclRef(CI.first, Record); - Writer.AddIdentifierRef(CI.second, Record); + Writer.AddDeclRef(CI.Decl, Record); + Writer.AddIdentifierRef(CI.Name, Record); + Writer.AddSourceLocation(CI.Loc, Record); } for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end(); diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 774372c86934..be5bb0dade87 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -52,7 +52,7 @@ static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI, if (MI.isGNUVarargs()) OS << "..."; // #define foo(x...) - + OS << ')'; } @@ -102,7 +102,7 @@ public: EmittedMacroOnThisLine = false; FileType = SrcMgr::C_User; Initialized = false; - + // If we're in microsoft mode, use normal #line instead of line markers. UseLineDirective = PP.getLangOptions().Microsoft; } @@ -150,7 +150,7 @@ void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo, OS << '#' << ' ' << LineNo << ' ' << '"'; OS.write(&CurFilename[0], CurFilename.size()); OS << '"'; - + if (ExtraLen) OS.write(Extra, ExtraLen); @@ -492,7 +492,7 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS, PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC", Callbacks)); - PP.setPPCallbacks(Callbacks); + PP.addPPCallbacks(Callbacks); // After we have configured the preprocessor, enter the main file. PP.EnterMainSourceFile(); diff --git a/lib/Headers/smmintrin.h b/lib/Headers/smmintrin.h index d91ed1da7b28..b3bdac68855e 100644 --- a/lib/Headers/smmintrin.h +++ b/lib/Headers/smmintrin.h @@ -32,6 +32,7 @@ /* Type defines. */ typedef double __v2df __attribute__ ((__vector_size__ (16))); +typedef long long __v2di __attribute__ ((__vector_size__ (16))); /* SSE4 Rounding macros. */ #define _MM_FROUND_TO_NEAREST_INT 0x00 @@ -48,7 +49,7 @@ typedef double __v2df __attribute__ ((__vector_size__ (16))); #define _MM_FROUND_CEIL (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_POS_INF) #define _MM_FROUND_TRUNC (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_ZERO) #define _MM_FROUND_RINT (_MM_FROUND_RAISE_EXC | _MM_FROUND_CUR_DIRECTION) -#define _MM_FROUND_NEARBYINT (_MM_FROUND_RAISE_EXC | _MM_FROUND_CUR_DIRECTION) +#define _MM_FROUND_NEARBYINT (_MM_FROUND_NO_EXC | _MM_FROUND_CUR_DIRECTION) #define _mm_ceil_ps(X) _mm_round_ps((X), _MM_FROUND_CEIL) #define _mm_ceil_pd(X) _mm_round_pd((X), _MM_FROUND_CEIL) @@ -60,30 +61,10 @@ typedef double __v2df __attribute__ ((__vector_size__ (16))); #define _mm_floor_ss(X, Y) _mm_round_ss((X), (Y), _MM_FROUND_FLOOR) #define _mm_floor_sd(X, Y) _mm_round_sd((X), (Y), _MM_FROUND_FLOOR) -/* SSE4 Rounding Intrinsics. */ -static inline __m128 __attribute__((__always_inline__, __nodebug__)) -_mm_round_ps (__m128 __V, const int __M) -{ - return (__m128) __builtin_ia32_roundps ((__v4sf)__V, __M); -} - -static inline __m128 __attribute__((__always_inline__, __nodebug__)) -_mm_round_ss (__m128 __V1, __m128 __V2, const int __M) -{ - return (__m128) __builtin_ia32_roundss ((__v4sf)__V1, (__v4sf)__V2, __M); -} - -static inline __m128d __attribute__((__always_inline__, __nodebug__)) -_mm_round_pd (__m128d __V, const int __M) -{ - return (__m128d) __builtin_ia32_roundpd ((__v2df)__V, __M); -} - -static inline __m128d __attribute__((__always_inline__, __nodebug__)) -_mm_round_sd(__m128d __V1, __m128d __V2, const int __M) -{ - return (__m128d) __builtin_ia32_roundsd ((__v2df)__V1, (__v2df)__V2, __M); -} +#define _mm_round_ps(X, Y) __builtin_ia32_roundps((X), (Y)) +#define _mm_round_ss(X, Y, M) __builtin_ia32_roundss((X), (Y), (M)) +#define _mm_round_pd(X, M) __builtin_ia32_roundpd((X), (M)) +#define _mm_round_sd(X, Y, M) __builtin_ia32_roundsd((X), (Y), (M)) /* SSE4 Packed Blending Intrinsics. */ static inline __m128d __attribute__((__always_inline__, __nodebug__)) @@ -125,6 +106,100 @@ _mm_blend_epi16 (__m128i __V1, __m128i __V2, const int __M) return (__m128i) __builtin_ia32_pblendw128 ((__v8hi)__V1, (__v8hi)__V2, __M); } +/* SSE4 Dword Multiply Instructions. */ +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_mullo_epi32 (__m128i __V1, __m128i __V2) +{ + return (__m128i) __builtin_ia32_pmulld128((__v4si)__V1, (__v4si)__V2); +} + +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_mul_epi32 (__m128i __V1, __m128i __V2) +{ + return (__m128i) __builtin_ia32_pmuldq128 ((__v4si)__V1, (__v4si)__V2); +} + +/* SSE4 Floating Point Dot Product Instructions. */ +#define _mm_dp_ps(X, Y, M) __builtin_ia32_dpps ((X), (Y), (M)) +#define _mm_dp_pd(X, Y, M) __builtin_ia32_dppd ((X), (Y), (M)) + +/* SSE4 Streaming Load Hint Instruction. */ +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_stream_load_si128 (__m128i *__V) +{ + return (__m128i) __builtin_ia32_movntdqa ((__v2di *) __V); +} + +/* SSE4 Packed Integer Min/Max Instructions. */ +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_min_epi8 (__m128i __V1, __m128i __V2) +{ + return (__m128i) __builtin_ia32_pminsb128 ((__v16qi) __V1, (__v16qi) __V2); +} + +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_max_epi8 (__m128i __V1, __m128i __V2) +{ + return (__m128i) __builtin_ia32_pmaxsb128 ((__v16qi) __V1, (__v16qi) __V2); +} + +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_min_epu16 (__m128i __V1, __m128i __V2) +{ + return (__m128i) __builtin_ia32_pminuw128 ((__v8hi) __V1, (__v8hi) __V2); +} + +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_max_epu16 (__m128i __V1, __m128i __V2) +{ + return (__m128i) __builtin_ia32_pmaxuw128 ((__v8hi) __V1, (__v8hi) __V2); +} + +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_min_epi32 (__m128i __V1, __m128i __V2) +{ + return (__m128i) __builtin_ia32_pminsd128 ((__v4si) __V1, (__v4si) __V2); +} + +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_max_epi32 (__m128i __V1, __m128i __V2) +{ + return (__m128i) __builtin_ia32_pmaxsd128 ((__v4si) __V1, (__v4si) __V2); +} + +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_min_epu32 (__m128i __V1, __m128i __V2) +{ + return (__m128i) __builtin_ia32_pminud128((__v4si) __V1, (__v4si) __V2); +} + +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_max_epu32 (__m128i __V1, __m128i __V2) +{ + return (__m128i) __builtin_ia32_pmaxud128((__v4si) __V1, (__v4si) __V2); +} + +/* SSE4 Insertion and Extraction from XMM Register Instructions. */ +#define _mm_insert_ps(X, Y, N) __builtin_ia32_insertps128((X), (Y), (N)) +#define _mm_extract_ps(X, N) (__extension__ \ + ({ union { int i; float f; } __t; \ + __v4sf __a = (__v4sf)X; \ + __t.f = __a[N]; \ + __t.i;})) + +/* Miscellaneous insert and extract macros. */ +/* Extract a single-precision float from X at index N into D. */ +#define _MM_EXTRACT_FLOAT(D, X, N) (__extension__ ({ __v4sf __a = (__v4sf)X; \ + (D) = __a[N]; })) + +/* Or together 2 sets of indexes (X and Y) with the zeroing bits (Z) to create + an index suitable for _mm_insert_ps. */ +#define _MM_MK_INSERTPS_NDX(X, Y, Z) (((X) << 6) | ((Y) << 4) | (Z)) + +/* Extract a float from X at index N into the first index of the return. */ +#define _MM_PICK_OUT_PS(X, N) _mm_insert_ps (_mm_setzero_ps(), (X), \ + _MM_MK_INSERTPS_NDX((N), 0, 0x0e)) + #endif /* __SSE4_1__ */ #endif /* _SMMINTRIN_H */ diff --git a/lib/Headers/stdarg.h b/lib/Headers/stdarg.h index bbbaff93e242..c36ab12019fe 100644 --- a/lib/Headers/stdarg.h +++ b/lib/Headers/stdarg.h @@ -26,7 +26,10 @@ #ifndef __STDARG_H #define __STDARG_H +#ifndef _VA_LIST typedef __builtin_va_list va_list; +#define _VA_LIST +#endif #define va_start(ap, param) __builtin_va_start(ap, param) #define va_end(ap) __builtin_va_end(ap) #define va_arg(ap, type) __builtin_va_arg(ap, type) diff --git a/lib/Headers/stddef.h b/lib/Headers/stddef.h index 2c84b4b066c9..6868ad341fd6 100644 --- a/lib/Headers/stddef.h +++ b/lib/Headers/stddef.h @@ -27,11 +27,18 @@ #define __STDDEF_H typedef __typeof__(((int*)0)-((int*)0)) ptrdiff_t; +#ifndef _SIZE_T +#define _SIZE_T typedef __typeof__(sizeof(int)) size_t; +#endif #ifndef __cplusplus +#ifndef _WCHAR_T +#define _WCHAR_T typedef __typeof__(*L"") wchar_t; #endif +#endif +#undef NULL #ifdef __cplusplus #define NULL __null #else diff --git a/lib/Index/Analyzer.cpp b/lib/Index/Analyzer.cpp index fb3529d5405c..7b414f2a9fb5 100644 --- a/lib/Index/Analyzer.cpp +++ b/lib/Index/Analyzer.cpp @@ -177,7 +177,7 @@ public: if (IsInstanceMethod) return false; - MsgD = Msg->getClassInfo().first; + MsgD = Msg->getClassInfo().Decl; // FIXME: Case when we only have an identifier. assert(MsgD && "Identifier only"); } @@ -250,7 +250,7 @@ public: while (true) { if (Msg->getReceiver() == 0) { CanBeClassMethod = true; - MsgD = Msg->getClassInfo().first; + MsgD = Msg->getClassInfo().Decl; // FIXME: Case when we only have an identifier. assert(MsgD && "Identifier only"); break; diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index 8c4caafeac24..299e84e33eff 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -17,7 +17,6 @@ #include "clang-c/Index.h" #include "Sema.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cstring> diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index 7cf207f77aa8..1c761b95039c 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -85,6 +85,8 @@ static unsigned GetDiagForGotoScopeDecl(const Decl *D, bool isCPlusPlus) { return diag::note_protected_by_cleanup; if (VD->hasAttr<BlocksAttr>()) return diag::note_protected_by___block; + // FIXME: In C++0x, we have to check more conditions than "did we + // just give it an initializer?". See 6.7p3. if (isCPlusPlus && VD->hasLocalStorage() && VD->hasInit()) return diag::note_protected_by_variable_init; diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 0097cd363c8c..e04abd2aac97 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -84,7 +84,8 @@ static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType, QualType OrigSrcType, QualType OrigDestType, unsigned &msg, CastExpr::CastKind &Kind); -static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, +static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, + QualType SrcType, QualType DestType,bool CStyle, const SourceRange &OpRange, unsigned &msg, @@ -554,7 +555,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // Reverse member pointer conversion. C++ 4.11 specifies member pointer // conversion. C++ 5.2.9p9 has additional information. // DR54's access restrictions apply here also. - tcr = TryStaticMemberPointerUpcast(Self, SrcType, DestType, CStyle, + tcr = TryStaticMemberPointerUpcast(Self, SrcExpr, SrcType, DestType, CStyle, OpRange, msg, Kind); if (tcr != TC_NotApplicable) return tcr; @@ -798,12 +799,23 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, /// where B is a base class of D [...]. /// TryCastResult -TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType, - bool CStyle, const SourceRange &OpRange, +TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, + QualType DestType, bool CStyle, + const SourceRange &OpRange, unsigned &msg, CastExpr::CastKind &Kind) { const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>(); if (!DestMemPtr) return TC_NotApplicable; + + bool WasOverloadedFunction = false; + if (FunctionDecl *Fn + = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false)) { + CXXMethodDecl *M = cast<CXXMethodDecl>(Fn); + SrcType = Self.Context.getMemberPointerType(Fn->getType(), + Self.Context.getTypeDeclType(M->getParent()).getTypePtr()); + WasOverloadedFunction = true; + } + const MemberPointerType *SrcMemPtr = SrcType->getAs<MemberPointerType>(); if (!SrcMemPtr) { msg = diag::err_bad_static_cast_member_pointer_nonmp; @@ -853,6 +865,24 @@ TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType, return TC_Failed; } + if (WasOverloadedFunction) { + // Resolve the address of the overloaded function again, this time + // allowing complaints if something goes wrong. + FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr, + DestType, + true); + if (!Fn) { + msg = 0; + return TC_Failed; + } + + SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, Fn); + if (!SrcExpr) { + msg = 0; + return TC_Failed; + } + } + Kind = CastExpr::CK_DerivedToBaseMemberPointer; return TC_Success; } diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 971b78c489e8..95b79abd8f70 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -76,14 +76,6 @@ getCurrentInstantiationOf(ASTContext &Context, DeclContext *CurContext, // our context. if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T) return Record; - - if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) { - QualType InjectedClassName - = Template->getInjectedClassNameType(Context); - if (T == Context.getCanonicalType(InjectedClassName)) - return Template->getTemplatedDecl(); - } - // FIXME: check for class template partial specializations } return 0; @@ -130,8 +122,11 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, return Record; if (EnteringContext) { - if (const TemplateSpecializationType *SpecType - = dyn_cast_or_null<TemplateSpecializationType>(NNS->getAsType())) { + const Type *NNSType = NNS->getAsType(); + if (!NNSType) { + // do nothing, fall out + } else if (const TemplateSpecializationType *SpecType + = NNSType->getAs<TemplateSpecializationType>()) { // We are entering the context of the nested name specifier, so try to // match the nested name specifier to either a primary class template // or a class template partial specialization. @@ -144,7 +139,8 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, // If the type of the nested name specifier is the same as the // injected class name of the named class template, we're entering // into that class template definition. - QualType Injected = ClassTemplate->getInjectedClassNameType(Context); + QualType Injected + = ClassTemplate->getInjectedClassNameSpecialization(Context); if (Context.hasSameType(Injected, ContextType)) return ClassTemplate->getTemplatedDecl(); @@ -156,8 +152,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, = ClassTemplate->findPartialSpecialization(ContextType)) return PartialSpec; } - } else if (const RecordType *RecordT - = dyn_cast_or_null<RecordType>(NNS->getAsType())) { + } else if (const RecordType *RecordT = NNSType->getAs<RecordType>()) { // The nested name specifier refers to a member of a class template. return RecordT->getDecl(); } @@ -248,7 +243,7 @@ bool Sema::RequireCompleteDeclContext(const CXXScopeSpec &SS) { // If we're currently defining this type, then lookup into the // type is okay: don't complain that it isn't complete yet. const TagType *TagT = Context.getTypeDeclType(Tag)->getAs<TagType>(); - if (TagT->isBeingDefined()) + if (TagT && TagT->isBeingDefined()) return false; // The type must be complete. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index ec1939e5ece9..94fcfc6c29e6 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -188,18 +188,6 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) { DiagnoseUseOfDecl(IIDecl, NameLoc); - // C++ [temp.local]p2: - // Within the scope of a class template specialization or - // partial specialization, when the injected-class-name is - // not followed by a <, it is equivalent to the - // injected-class-name followed by the template-argument s - // of the class template specialization or partial - // specialization enclosed in <>. - if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) - if (RD->isInjectedClassName()) - if (ClassTemplateDecl *Template = RD->getDescribedClassTemplate()) - T = Template->getInjectedClassNameType(Context); - if (T.isNull()) T = Context.getTypeDeclType(TD); @@ -1773,12 +1761,7 @@ DeclarationName Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { return DeclarationName(); // Determine the type of the class being constructed. - QualType CurClassType; - if (ClassTemplateDecl *ClassTemplate - = CurClass->getDescribedClassTemplate()) - CurClassType = ClassTemplate->getInjectedClassNameType(Context); - else - CurClassType = Context.getTypeDeclType(CurClass); + QualType CurClassType = Context.getTypeDeclType(CurClass); // FIXME: Check two things: that the template-id names the same type as // CurClassType, and that the template-id does not occur when the name @@ -3809,24 +3792,38 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, return; } - InitializedEntity Entity = InitializedEntity::InitializeVariable(Var); - InitializationKind Kind - = InitializationKind::CreateDefault(Var->getLocation()); + const RecordType *Record + = Context.getBaseElementType(Type)->getAs<RecordType>(); + if (Record && getLangOptions().CPlusPlus && !getLangOptions().CPlusPlus0x && + cast<CXXRecordDecl>(Record->getDecl())->isPOD()) { + // C++03 [dcl.init]p9: + // If no initializer is specified for an object, and the + // object is of (possibly cv-qualified) non-POD class type (or + // array thereof), the object shall be default-initialized; if + // the object is of const-qualified type, the underlying class + // type shall have a user-declared default + // constructor. Otherwise, if no initializer is specified for + // a non- static object, the object and its subobjects, if + // any, have an indeterminate initial value); if the object + // or any of its subobjects are of const-qualified type, the + // program is ill-formed. + // FIXME: DPG thinks it is very fishy that C++0x disables this. + } else { + InitializedEntity Entity = InitializedEntity::InitializeVariable(Var); + InitializationKind Kind + = InitializationKind::CreateDefault(Var->getLocation()); - InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); - OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, 0, 0)); - if (Init.isInvalid()) - Var->setInvalidDecl(); - else { - if (Init.get()) + InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); + OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, 0, 0)); + if (Init.isInvalid()) + Var->setInvalidDecl(); + else if (Init.get()) Var->setInit(MaybeCreateCXXExprWithTemporaries(Init.takeAs<Expr>())); - - if (getLangOptions().CPlusPlus) - if (const RecordType *Record - = Context.getBaseElementType(Type)->getAs<RecordType>()) - FinalizeVarWithDestructor(Var, Record); } + + if (!Var->isInvalidDecl() && getLangOptions().CPlusPlus && Record) + FinalizeVarWithDestructor(Var, Record); } } @@ -5030,7 +5027,7 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD, // Exit this scope of this tag's definition. PopDeclContext(); - if (isa<CXXRecordDecl>(Tag) && !Tag->getDeclContext()->isRecord()) + if (isa<CXXRecordDecl>(Tag) && !Tag->getLexicalDeclContext()->isRecord()) RecordDynamicClassesWithNoKeyFunction(*this, cast<CXXRecordDecl>(Tag), RBraceLoc); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 0708d4176a4f..e694cb470c25 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -665,22 +665,29 @@ void Sema::ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases, (CXXBaseSpecifier**)(Bases), NumBases); } +static CXXRecordDecl *GetClassForType(QualType T) { + if (const RecordType *RT = T->getAs<RecordType>()) + return cast<CXXRecordDecl>(RT->getDecl()); + else if (const InjectedClassNameType *ICT = T->getAs<InjectedClassNameType>()) + return ICT->getDecl(); + else + return 0; +} + /// \brief Determine whether the type \p Derived is a C++ class that is /// derived from the type \p Base. bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { if (!getLangOptions().CPlusPlus) return false; - - const RecordType *DerivedRT = Derived->getAs<RecordType>(); - if (!DerivedRT) + + CXXRecordDecl *DerivedRD = GetClassForType(Derived); + if (!DerivedRD) return false; - const RecordType *BaseRT = Base->getAs<RecordType>(); - if (!BaseRT) + CXXRecordDecl *BaseRD = GetClassForType(Base); + if (!BaseRD) return false; - CXXRecordDecl *DerivedRD = cast<CXXRecordDecl>(DerivedRT->getDecl()); - CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl()); // FIXME: instantiate DerivedRD if necessary. We need a PoI for this. return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD); } @@ -691,16 +698,14 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) { if (!getLangOptions().CPlusPlus) return false; - const RecordType *DerivedRT = Derived->getAs<RecordType>(); - if (!DerivedRT) + CXXRecordDecl *DerivedRD = GetClassForType(Derived); + if (!DerivedRD) return false; - const RecordType *BaseRT = Base->getAs<RecordType>(); - if (!BaseRT) + CXXRecordDecl *BaseRD = GetClassForType(Base); + if (!BaseRD) return false; - CXXRecordDecl *DerivedRD = cast<CXXRecordDecl>(DerivedRT->getDecl()); - CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl()); return DerivedRD->isDerivedFrom(BaseRD, Paths); } @@ -1083,6 +1088,9 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, // specialization, we take it as a type name. BaseType = CheckTypenameType((NestedNameSpecifier *)SS.getScopeRep(), *MemberOrBase, SS.getRange()); + if (BaseType.isNull()) + return true; + R.clear(); } } @@ -4526,20 +4534,23 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, OverloadCandidateSet::iterator Best; switch (BestViableFunction(CandidateSet, DeclLoc, Best)) { case OR_Success: + // C++ [over.ics.ref]p1: + // + // [...] If the parameter binds directly to the result of + // applying a conversion function to the argument + // expression, the implicit conversion sequence is a + // user-defined conversion sequence (13.3.3.1.2), with the + // second standard conversion sequence either an identity + // conversion or, if the conversion function returns an + // entity of a type that is a derived class of the parameter + // type, a derived-to-base Conversion. + if (!Best->FinalConversion.DirectBinding) + break; + // This is a direct binding. BindsDirectly = true; if (ICS) { - // C++ [over.ics.ref]p1: - // - // [...] If the parameter binds directly to the result of - // applying a conversion function to the argument - // expression, the implicit conversion sequence is a - // user-defined conversion sequence (13.3.3.1.2), with the - // second standard conversion sequence either an identity - // conversion or, if the conversion function returns an - // entity of a type that is a derived class of the parameter - // type, a derived-to-base Conversion. ICS->setUserDefined(); ICS->UserDefined.Before = Best->Conversions[0].Standard; ICS->UserDefined.After = Best->FinalConversion; @@ -5189,21 +5200,28 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType, Invalid = true; } + // GCC allows catching pointers and references to incomplete types + // as an extension; so do we, but we warn by default. + QualType BaseType = ExDeclType; int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference unsigned DK = diag::err_catch_incomplete; + bool IncompleteCatchIsInvalid = true; if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { BaseType = Ptr->getPointeeType(); Mode = 1; - DK = diag::err_catch_incomplete_ptr; + DK = diag::ext_catch_incomplete_ptr; + IncompleteCatchIsInvalid = false; } else if (const ReferenceType *Ref = BaseType->getAs<ReferenceType>()) { // For the purpose of error recovery, we treat rvalue refs like lvalue refs. BaseType = Ref->getPointeeType(); Mode = 2; - DK = diag::err_catch_incomplete_ref; + DK = diag::ext_catch_incomplete_ref; + IncompleteCatchIsInvalid = false; } if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) && - !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK)) + !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK) && + IncompleteCatchIsInvalid) Invalid = true; if (!Invalid && !ExDeclType->isDependentType() && @@ -5889,10 +5907,13 @@ void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc, // We will need to mark all of the virtual members as referenced to build the // vtable. - // We actually call MarkVirtualMembersReferenced instead of adding to - // ClassesWithUnmarkedVirtualMembers because this marking is needed by - // codegen that will happend before we finish parsing the file. - if (needsVtable(MD, Context)) + if (!needsVtable(MD, Context)) + return; + + TemplateSpecializationKind kind = RD->getTemplateSpecializationKind(); + if (kind == TSK_ImplicitInstantiation) + ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc)); + else MarkVirtualMembersReferenced(Loc, RD); } diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 149fe15fabec..762ef38c9736 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1681,7 +1681,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, // for this class. GetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(), property->getLocation(), property->getGetterName(), - property->getType(), CD, true, false, true, + property->getType(), 0, CD, true, false, true, (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) ? ObjCMethodDecl::Optional : @@ -1703,7 +1703,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, SetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(), property->getLocation(), property->getSetterName(), - Context.VoidTy, CD, true, false, true, + Context.VoidTy, 0, CD, true, false, true, (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) ? ObjCMethodDecl::Optional : @@ -1992,8 +1992,9 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( } QualType resultDeclType; + TypeSourceInfo *ResultTInfo = 0; if (ReturnType) { - resultDeclType = GetTypeFromParser(ReturnType); + resultDeclType = GetTypeFromParser(ReturnType, &ResultTInfo); // Methods cannot return interface types. All ObjC objects are // passed by reference. @@ -2007,6 +2008,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( ObjCMethodDecl* ObjCMethod = ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel, resultDeclType, + ResultTInfo, cast<DeclContext>(ClassDecl), MethodType == tok::minus, isVariadic, false, diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 10001c356d1c..2249579ba4e1 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -6593,7 +6593,8 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, StmtArg substmt, assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!"); CompoundStmt *Compound = cast<CompoundStmt>(SubStmt); - bool isFileScope = getCurFunctionOrMethodDecl() == 0; + bool isFileScope + = (getCurFunctionOrMethodDecl() == 0) && (getCurBlock() == 0); if (isFileScope) return ExprError(Diag(LPLoc, diag::err_stmtexpr_file_scope)); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 309da292e137..b9c8afa195fd 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -172,14 +172,6 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc, if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) { QualType T = Context.getTypeDeclType(Type); - // If we found the injected-class-name of a class template, retrieve the - // type of that template. - // FIXME: We really shouldn't need to do this. - if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Type)) - if (Record->isInjectedClassName()) - if (Record->getDescribedClassTemplate()) - T = Record->getDescribedClassTemplate() - ->getInjectedClassNameType(Context); if (SearchType.isNull() || SearchType->isDependentType() || Context.hasSameUnqualifiedType(T, SearchType)) { @@ -200,16 +192,8 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc, if (SS.isSet()) { if (DeclContext *Ctx = computeDeclContext(SS, EnteringContext)) { // Figure out the type of the context, if it has one. - if (ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) - MemberOfType = Context.getTypeDeclType(Spec); - else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) { - if (Record->getDescribedClassTemplate()) - MemberOfType = Record->getDescribedClassTemplate() - ->getInjectedClassNameType(Context); - else - MemberOfType = Context.getTypeDeclType(Record); - } + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) + MemberOfType = Context.getTypeDeclType(Record); } } if (MemberOfType.isNull()) diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 3a05241c016b..c60455d8456c 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -470,13 +470,13 @@ Sema::ExprResult Sema::ActOnClassMessage( // now, we simply pass the "super" identifier through (which isn't consistent // with instance methods. if (isSuper) - return new (Context) ObjCMessageExpr(Context, receiverName, Sel, returnType, - Method, lbrac, rbrac, ArgExprs, - NumArgs); + return new (Context) ObjCMessageExpr(Context, receiverName, receiverLoc, + Sel, returnType, Method, lbrac, rbrac, + ArgExprs, NumArgs); else - return new (Context) ObjCMessageExpr(Context, ClassDecl, Sel, returnType, - Method, lbrac, rbrac, ArgExprs, - NumArgs); + return new (Context) ObjCMessageExpr(Context, ClassDecl, receiverLoc, + Sel, returnType, Method, lbrac, rbrac, + ArgExprs, NumArgs); } // ActOnInstanceMessage - used for both unary and keyword messages. diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index bf9f73c96150..3540cd02e6da 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -18,6 +18,7 @@ #include "SemaInit.h" #include "Lookup.h" #include "Sema.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Parse/Designator.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ExprCXX.h" @@ -497,6 +498,20 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, = ParentIList->getInit(EndIndex)->getSourceRange().getEnd(); StructuredSubobjectInitList->setRBraceLoc(EndLoc); } + + // Warn about missing braces. + if (T->isArrayType() || T->isRecordType()) { + SemaRef.Diag(StructuredSubobjectInitList->getLocStart(), + diag::warn_missing_braces) + << StructuredSubobjectInitList->getSourceRange() + << CodeModificationHint::CreateInsertion( + StructuredSubobjectInitList->getLocStart(), + "{") + << CodeModificationHint::CreateInsertion( + SemaRef.PP.getLocForEndOfToken( + StructuredSubobjectInitList->getLocEnd()), + "}"); + } } void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, @@ -2258,10 +2273,17 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, Sema::ReferenceCompareResult NewRefRelationship = S.CompareReferenceRelationship(DeclLoc, T1, T2.getNonReferenceType(), NewDerivedToBase); - assert(NewRefRelationship != Sema::Ref_Incompatible && - "Overload resolution picked a bad conversion function"); - (void)NewRefRelationship; - if (NewDerivedToBase) + if (NewRefRelationship == Sema::Ref_Incompatible) { + // If the type we've converted to is not reference-related to the + // type we're looking for, then there is another conversion step + // we need to perform to produce a temporary of the right type + // that we'll be binding to. + ImplicitConversionSequence ICS; + ICS.setStandard(); + ICS.Standard = Best->FinalConversion; + T2 = ICS.Standard.getToType(2); + Sequence.AddConversionSequenceStep(ICS, T2); + } else if (NewDerivedToBase) Sequence.AddDerivedToBaseCastStep( S.Context.getQualifiedType(T1, T2.getNonReferenceType().getQualifiers()), diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 03219580f92f..7c4cab118366 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -871,10 +871,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, NewClass->setDescribedClassTemplate(NewTemplate); // Build the type for the class template declaration now. - QualType T = - Context.getTypeDeclType(NewClass, - PrevClassTemplate? - PrevClassTemplate->getTemplatedDecl() : 0); + QualType T = NewTemplate->getInjectedClassNameSpecialization(Context); + T = Context.getInjectedClassNameType(NewClass, T); assert(T->isDependentType() && "Class template type is not dependent?"); (void)T; @@ -1306,7 +1304,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, TemplateParameterList *ExpectedTemplateParams = 0; // Is this template-id naming the primary template? if (Context.hasSameType(TemplateId, - ClassTemplate->getInjectedClassNameType(Context))) + ClassTemplate->getInjectedClassNameSpecialization(Context))) ExpectedTemplateParams = ClassTemplate->getTemplateParameters(); // ... or a partial specialization? else if (ClassTemplatePartialSpecializationDecl *PartialSpec @@ -1431,6 +1429,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, } CanonType = Context.getTypeDeclType(Decl); + assert(isa<RecordType>(CanonType) && + "type of non-dependent specialization is not a RecordType"); } // Build the fully-sugared type for this class template @@ -3488,6 +3488,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, ClassTemplate, Converted, TemplateArgs, + CanonType, PrevPartial); if (PrevPartial) { @@ -3609,8 +3610,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // actually wrote the specialization, rather than formatting the // name based on the "canonical" representation used to store the // template arguments in the specialization. - QualType WrittenTy - = Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType); + TypeSourceInfo *WrittenTy + = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc, + TemplateArgs, CanonType); if (TUK != TUK_Friend) Specialization->setTypeAsWritten(WrittenTy); TemplateArgsIn.release(); @@ -3632,7 +3634,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, if (TUK == TUK_Friend) { FriendDecl *Friend = FriendDecl::Create(Context, CurContext, TemplateNameLoc, - WrittenTy.getTypePtr(), + WrittenTy->getType().getTypePtr(), /*FIXME:*/KWLoc); Friend->setAccess(AS_public); CurContext->addDecl(Friend); @@ -4344,8 +4346,9 @@ Sema::ActOnExplicitInstantiation(Scope *S, // the explicit instantiation, rather than formatting the name based // on the "canonical" representation used to store the template // arguments in the specialization. - QualType WrittenTy - = Context.getTemplateSpecializationType(Name, TemplateArgs, + TypeSourceInfo *WrittenTy + = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc, + TemplateArgs, Context.getTypeDeclType(Specialization)); Specialization->setTypeAsWritten(WrittenTy); TemplateArgsIn.release(); @@ -4992,6 +4995,9 @@ CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB, Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier(), SourceRange(TL.getNameLoc())); + if (Result.isNull()) + return QualType(); + TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result); NewTL.setNameLoc(TL.getNameLoc()); return Result; diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 7f16400aea8d..326519d3a378 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -625,6 +625,15 @@ DeduceTemplateArguments(Sema &S, return Sema::TDK_Success; } + case Type::InjectedClassName: { + // Treat a template's injected-class-name as if the template + // specialization type had been used. + Param = cast<InjectedClassNameType>(Param)->getUnderlyingType(); + assert(isa<TemplateSpecializationType>(Param) && + "injected class name is not a template specialization type"); + // fall through + } + // template-name<T> (where template-name refers to a class template) // template-name<i> // TT<T> diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 3a6b4cb3cc1f..cf8d38c09583 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -621,7 +621,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { Inst->setInstantiatedFromMemberTemplate(D); // Trigger creation of the type for the instantiation. - SemaRef.Context.getTypeDeclType(RecordInst); + SemaRef.Context.getInjectedClassNameType(RecordInst, + Inst->getInjectedClassNameSpecialization(SemaRef.Context)); // Finish handling of friends. if (Inst->getFriendObjectKind()) { @@ -1462,8 +1463,10 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( // actually wrote the specialization, rather than formatting the // name based on the "canonical" representation used to store the // template arguments in the specialization. - QualType WrittenTy - = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate), + TypeSourceInfo *WrittenTy + = SemaRef.Context.getTemplateSpecializationTypeInfo( + TemplateName(ClassTemplate), + PartialSpec->getLocation(), InstTemplateArgs, CanonType); @@ -1499,6 +1502,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( ClassTemplate, Converted, InstTemplateArgs, + CanonType, 0); InstPartialSpec->setInstantiatedFromMember(PartialSpec); InstPartialSpec->setTypeAsWritten(WrittenTy); @@ -2236,12 +2240,18 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate(); if (ClassTemplate) { - T = ClassTemplate->getInjectedClassNameType(Context); + T = ClassTemplate->getInjectedClassNameSpecialization(Context); } else if (ClassTemplatePartialSpecializationDecl *PartialSpec = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) { - T = Context.getTypeDeclType(Record); ClassTemplate = PartialSpec->getSpecializedTemplate(); - } + + // If we call SubstType with an InjectedClassNameType here we + // can end up in an infinite loop. + T = Context.getTypeDeclType(Record); + assert(isa<InjectedClassNameType>(T) && + "type of partial specialization is not an InjectedClassNameType"); + T = cast<InjectedClassNameType>(T)->getUnderlyingType(); + } if (!T.isNull()) { // Substitute into the injected-class-name to get the type @@ -2308,16 +2318,16 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, // so now we need to look into the instantiated parent context to // find the instantiation of the declaration D. - // If our context is a class template specialization, we may need - // to instantiate it before performing lookup into that context. - if (ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(ParentDC)) { + // If our context used to be dependent, we may need to instantiate + // it before performing lookup into that context. + if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) { if (!Spec->isDependentContext()) { QualType T = Context.getTypeDeclType(Spec); - if (const TagType *Tag = T->getAs<TagType>()) - if (!Tag->isBeingDefined() && - RequireCompleteType(Loc, T, diag::err_incomplete_type)) - return 0; + const RecordType *Tag = T->getAs<RecordType>(); + assert(Tag && "type of non-dependent record is not a RecordType"); + if (!Tag->isBeingDefined() && + RequireCompleteType(Loc, T, diag::err_incomplete_type)) + return 0; } } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 24ea62cde1b4..17f94193fed4 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2823,6 +2823,20 @@ QualType TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB, return Result; } +template<typename Derived> +QualType TreeTransform<Derived>::TransformInjectedClassNameType( + TypeLocBuilder &TLB, + InjectedClassNameTypeLoc TL, + QualType ObjectType) { + Decl *D = getDerived().TransformDecl(TL.getNameLoc(), + TL.getTypePtr()->getDecl()); + if (!D) return QualType(); + + QualType T = SemaRef.Context.getTypeDeclType(cast<TypeDecl>(D)); + TLB.pushTypeSpec(T).setNameLoc(TL.getNameLoc()); + return T; +} + template<typename Derived> QualType TreeTransform<Derived>::TransformTemplateTypeParmType( diff --git a/test/Analysis/dead-stores.c b/test/Analysis/dead-stores.c index a00217442053..9a266c937939 100644 --- a/test/Analysis/dead-stores.c +++ b/test/Analysis/dead-stores.c @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code %s +// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s void f1() { int k, y; @@ -377,7 +377,7 @@ void f24_A(int y) { // FIXME: One day this should be reported as dead since 'z = x + y' is dead. int x = (y > 2); // no-warning ^ { - int z = x + y; // FIXME: Eventually this should be reported as a dead store. + int z = x + y; // expected-warning{{Value stored to 'z' during its initialization is never read}} }(); } @@ -429,3 +429,17 @@ int f25_b(int y) { return z; } +int f26_nestedblocks() { + int z; + z = 1; + __block int y = 0; + ^{ + int k; + k = 1; // expected-warning{{Value stored to 'k' is never read}} + ^{ + y = z + 1; + }(); + }(); + return y; +} + diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c index 3cce1b0d2ef4..21b6d46a245e 100644 --- a/test/Analysis/malloc.c +++ b/test/Analysis/malloc.c @@ -61,3 +61,9 @@ void pr6069() { void pr6293() { free(0); } + +void f7() { + char *x = (char*) malloc(4); + free(x); + x[0] = 'a'; // expected-warning{{Use dynamically allocated memory after it is freed.}} +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 245fe1f5f2a3..6bb5b6c3a0c2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -9,6 +9,7 @@ set(CLANG_TEST_DIRECTORIES "Driver" "FixIt" "Frontend" + "Headers" "Index" "Lexer" "Misc" diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp index 7a6210007eb9..f9bac40c9ddb 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp @@ -57,9 +57,9 @@ void test3() { int i = Ints::zero; Numbers2::f(i); - Numbers2::g(i); // expected-error {{no viable conversion from 'int' to 'struct Numbers::Number' is possible}} + Numbers2::g(i); // expected-error {{no viable conversion from 'int' to 'Numbers::Number'}} float f = Floats::zero; Numbers2::f(f); - Numbers2::g(f); // expected-error {{no viable conversion from 'float' to 'struct Numbers::Number' is possible}} + Numbers2::g(f); // expected-error {{no viable conversion from 'float' to 'Numbers::Number'}} } diff --git a/test/CXX/class.access/class.friend/p1.cpp b/test/CXX/class.access/class.friend/p1.cpp index 22f77b095511..a06fb2e3e3c2 100644 --- a/test/CXX/class.access/class.friend/p1.cpp +++ b/test/CXX/class.access/class.friend/p1.cpp @@ -22,10 +22,10 @@ void test1() { S s; g()->f(); S::f(); - X::g(); // expected-error{{no member named 'g' in 'struct X'}} - X::S x_s; // expected-error{{no member named 'S' in 'struct X'}} + X::g(); // expected-error{{no member named 'g' in 'X'}} + X::S x_s; // expected-error{{no member named 'S' in 'X'}} X x; - x.g(); // expected-error{{no member named 'g' in 'struct X'}} + x.g(); // expected-error{{no member named 'g' in 'X'}} } // Test that we recurse through namespaces to find already declared names, but @@ -46,17 +46,17 @@ namespace N { g()->f(); S s; S::f(); - X::g(); // expected-error{{no member named 'g' in 'struct N::X'}} - X::S x_s; // expected-error{{no member named 'S' in 'struct N::X'}} + X::g(); // expected-error{{no member named 'g' in 'N::X'}} + X::S x_s; // expected-error{{no member named 'S' in 'N::X'}} X x; - x.g(); // expected-error{{no member named 'g' in 'struct N::X'}} + x.g(); // expected-error{{no member named 'g' in 'N::X'}} g2(); S2 s2; ::g2(); // expected-error{{no member named 'g2' in the global namespace}} ::S2 g_s2; // expected-error{{no member named 'S2' in the global namespace}} - X::g2(); // expected-error{{no member named 'g2' in 'struct N::X'}} - X::S2 x_s2; // expected-error{{no member named 'S2' in 'struct N::X'}} - x.g2(); // expected-error{{no member named 'g2' in 'struct N::X'}} + X::g2(); // expected-error{{no member named 'g2' in 'N::X'}} + X::S2 x_s2; // expected-error{{no member named 'S2' in 'N::X'}} + x.g2(); // expected-error{{no member named 'g2' in 'N::X'}} } } diff --git a/test/CXX/class/class.friend/p1.cpp b/test/CXX/class/class.friend/p1.cpp index 886fef5bc4f6..3ad4a5f08289 100644 --- a/test/CXX/class/class.friend/p1.cpp +++ b/test/CXX/class/class.friend/p1.cpp @@ -67,7 +67,7 @@ class A { class facet {}; }; -A::UndeclaredSoFar y; // expected-error {{no type named 'UndeclaredSoFar' in 'class A'}} +A::UndeclaredSoFar y; // expected-error {{no type named 'UndeclaredSoFar' in 'A'}} class PreDeclared; diff --git a/test/CXX/class/class.local/p2.cpp b/test/CXX/class/class.local/p2.cpp index 8d281a57e137..2b1359c3d8d3 100644 --- a/test/CXX/class/class.local/p2.cpp +++ b/test/CXX/class/class.local/p2.cpp @@ -7,5 +7,5 @@ void f() { B b; - A *a = &b; // expected-error{{cannot cast 'struct B' to its private base class 'struct A'}} + A *a = &b; // expected-error{{cannot cast 'B' to its private base class 'A'}} } diff --git a/test/CXX/class/class.union/p1.cpp b/test/CXX/class/class.union/p1.cpp index 87946484ec18..f53783eb5f3a 100644 --- a/test/CXX/class/class.union/p1.cpp +++ b/test/CXX/class/class.union/p1.cpp @@ -7,30 +7,30 @@ class Okay { }; class Virtual { - virtual void foo() { abort(); } // expected-note 3 {{because type 'class Virtual' has a virtual member function}} + virtual void foo() { abort(); } // expected-note 3 {{because type 'Virtual' has a virtual member function}} }; -class VirtualBase : virtual Okay { // expected-note 3 {{because type 'class VirtualBase' has a virtual base class}} +class VirtualBase : virtual Okay { // expected-note 3 {{because type 'VirtualBase' has a virtual base class}} }; class Ctor { - Ctor() { abort(); } // expected-note 3 {{because type 'class Ctor' has a user-declared constructor}} + Ctor() { abort(); } // expected-note 3 {{because type 'Ctor' has a user-declared constructor}} }; class Ctor2 { - Ctor2(); // expected-note 3 {{because type 'class Ctor2' has a user-declared constructor}} + Ctor2(); // expected-note 3 {{because type 'Ctor2' has a user-declared constructor}} }; class CopyCtor { - CopyCtor(CopyCtor &cc) { abort(); } // expected-note 3 {{because type 'class CopyCtor' has a user-declared copy constructor}} + CopyCtor(CopyCtor &cc) { abort(); } // expected-note 3 {{because type 'CopyCtor' has a user-declared copy constructor}} }; // FIXME: this should eventually trigger on the operator's declaration line -class CopyAssign { // expected-note 3 {{because type 'class CopyAssign' has a user-declared copy assignment operator}} +class CopyAssign { // expected-note 3 {{because type 'CopyAssign' has a user-declared copy assignment operator}} CopyAssign& operator=(CopyAssign& CA) { abort(); } }; class Dtor { - ~Dtor() { abort(); } // expected-note 3 {{because type 'class Dtor' has a user-declared destructor}} + ~Dtor() { abort(); } // expected-note 3 {{because type 'Dtor' has a user-declared destructor}} }; union U1 { @@ -46,25 +46,25 @@ union U1 { union U2 { struct { - Virtual v; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial copy constructor}} + Virtual v; // expected-note {{because type 'U2::<anonymous>' has a member with a non-trivial copy constructor}} } m1; // expected-error {{union member 'm1' has a non-trivial copy constructor}} struct { - VirtualBase vbase; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial copy constructor}} + VirtualBase vbase; // expected-note {{because type 'U2::<anonymous>' has a member with a non-trivial copy constructor}} } m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}} struct { - Ctor ctor; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial constructor}} + Ctor ctor; // expected-note {{because type 'U2::<anonymous>' has a member with a non-trivial constructor}} } m3; // expected-error {{union member 'm3' has a non-trivial constructor}} struct { - Ctor2 ctor2; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial constructor}} + Ctor2 ctor2; // expected-note {{because type 'U2::<anonymous>' has a member with a non-trivial constructor}} } m3a; // expected-error {{union member 'm3a' has a non-trivial constructor}} struct { - CopyCtor copyctor; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial copy constructor}} + CopyCtor copyctor; // expected-note {{because type 'U2::<anonymous>' has a member with a non-trivial copy constructor}} } m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}} struct { - CopyAssign copyassign; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial copy assignment operator}} + CopyAssign copyassign; // expected-note {{because type 'U2::<anonymous>' has a member with a non-trivial copy assignment operator}} } m5; // expected-error {{union member 'm5' has a non-trivial copy assignment operator}} struct { - Dtor dtor; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial destructor}} + Dtor dtor; // expected-note {{because type 'U2::<anonymous>' has a member with a non-trivial destructor}} } m6; // expected-error {{union member 'm6' has a non-trivial destructor}} struct { Okay okay; @@ -72,19 +72,19 @@ union U2 { }; union U3 { - struct s1 : Virtual { // expected-note {{because type 'struct U3::s1' has a base class with a non-trivial copy constructor}} + struct s1 : Virtual { // expected-note {{because type 'U3::s1' has a base class with a non-trivial copy constructor}} } m1; // expected-error {{union member 'm1' has a non-trivial copy constructor}} - struct s2 : VirtualBase { // expected-note {{because type 'struct U3::s2' has a base class with a non-trivial copy constructor}} + struct s2 : VirtualBase { // expected-note {{because type 'U3::s2' has a base class with a non-trivial copy constructor}} } m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}} - struct s3 : Ctor { // expected-note {{because type 'struct U3::s3' has a base class with a non-trivial constructor}} + struct s3 : Ctor { // expected-note {{because type 'U3::s3' has a base class with a non-trivial constructor}} } m3; // expected-error {{union member 'm3' has a non-trivial constructor}} - struct s3a : Ctor2 { // expected-note {{because type 'struct U3::s3a' has a base class with a non-trivial constructor}} + struct s3a : Ctor2 { // expected-note {{because type 'U3::s3a' has a base class with a non-trivial constructor}} } m3a; // expected-error {{union member 'm3a' has a non-trivial constructor}} - struct s4 : CopyCtor { // expected-note {{because type 'struct U3::s4' has a base class with a non-trivial copy constructor}} + struct s4 : CopyCtor { // expected-note {{because type 'U3::s4' has a base class with a non-trivial copy constructor}} } m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}} - struct s5 : CopyAssign { // expected-note {{because type 'struct U3::s5' has a base class with a non-trivial copy assignment operator}} + struct s5 : CopyAssign { // expected-note {{because type 'U3::s5' has a base class with a non-trivial copy assignment operator}} } m5; // expected-error {{union member 'm5' has a non-trivial copy assignment operator}} - struct s6 : Dtor { // expected-note {{because type 'struct U3::s6' has a base class with a non-trivial destructor}} + struct s6 : Dtor { // expected-note {{because type 'U3::s6' has a base class with a non-trivial destructor}} } m6; // expected-error {{union member 'm6' has a non-trivial destructor}} struct s7 : Okay { } m7; diff --git a/test/CXX/conv/conv.mem/p4.cpp b/test/CXX/conv/conv.mem/p4.cpp index 1ecbc47ffbb8..42f6343e069e 100644 --- a/test/CXX/conv/conv.mem/p4.cpp +++ b/test/CXX/conv/conv.mem/p4.cpp @@ -19,8 +19,8 @@ namespace test0 { namespace test1 { struct Derived : private Base {}; // expected-note 2 {{declared private here}} void test() { - int (Derived::*d) = data_ptr; // expected-error {{cannot cast private base class 'struct Base' to 'struct test1::Derived'}} - int (Derived::*m)() = method_ptr; // expected-error {{cannot cast private base class 'struct Base' to 'struct test1::Derived'}} + int (Derived::*d) = data_ptr; // expected-error {{cannot cast private base class 'Base' to 'test1::Derived'}} + int (Derived::*m)() = method_ptr; // expected-error {{cannot cast private base class 'Base' to 'test1::Derived'}} } }; @@ -30,8 +30,8 @@ namespace test2 { struct B : Base {}; struct Derived : A, B {}; void test() { - int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'struct Base' to pointer to member of derived class 'struct test2::Derived'}} - int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'struct Base' to pointer to member of derived class 'struct test2::Derived'}} + int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test2::Derived':}} + int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test2::Derived':}} } } @@ -39,8 +39,8 @@ namespace test2 { namespace test3 { struct Derived : virtual Base {}; void test() { - int (Derived::*d) = data_ptr; // expected-error {{conversion from pointer to member of class 'struct Base' to pointer to member of class 'struct test3::Derived' via virtual base 'struct Base' is not allowed}} - int (Derived::*m)() = method_ptr; // expected-error {{conversion from pointer to member of class 'struct Base' to pointer to member of class 'struct test3::Derived' via virtual base 'struct Base' is not allowed}} + int (Derived::*d) = data_ptr; // expected-error {{conversion from pointer to member of class 'Base' to pointer to member of class 'test3::Derived' via virtual base 'Base' is not allowed}} + int (Derived::*m)() = method_ptr; // expected-error {{conversion from pointer to member of class 'Base' to pointer to member of class 'test3::Derived' via virtual base 'Base' is not allowed}} } } @@ -49,8 +49,8 @@ namespace test4 { struct A : Base {}; struct Derived : Base, virtual A {}; void test() { - int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'struct Base' to pointer to member of derived class 'struct test4::Derived'}} - int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'struct Base' to pointer to member of derived class 'struct test4::Derived'}} + int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test4::Derived':}} + int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test4::Derived':}} } } diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp index 7bfb655db99b..f507eecb4223 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -verify %s -struct S; // expected-note {{forward declaration of 'struct S'}} +struct S; // expected-note {{forward declaration of 'S'}} extern S a; extern S f(); // expected-note {{'f' declared here}} extern void g(S a); // expected-note {{candidate function}} @@ -8,5 +8,5 @@ extern void g(S a); // expected-note {{candidate function}} void h() { // FIXME: This diagnostic could be better. g(a); // expected-error {{no matching function for call to 'g'}} - f(); // expected-error {{calling 'f' with incomplete return type 'struct S'}} + f(); // expected-error {{calling 'f' with incomplete return type 'S'}} } diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp index 7c63a79de1c6..d757adf6986c 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp @@ -16,10 +16,10 @@ struct B : A { } b; // CHECK: example1 void example1() { - // CHECK: struct A &ra = + // CHECK: A &ra = // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase> lvalue A &ra = b; - // CHECK: struct A const &rca = + // CHECK: A const &rca = // CHECK: ImplicitCastExpr{{.*}}'struct A const' <NoOp> // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase> const A& rca = b; @@ -33,12 +33,12 @@ struct X { // CHECK: example2 void example2() { - // CHECK: struct A const &rca = + // CHECK: A const &rca = // CHECK: ImplicitCastExpr{{.*}}'struct A const' <NoOp> // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase> - // CHECK: CallExpr{{.*}}struct B + // CHECK: CallExpr{{.*}}B const A &rca = f(); - // CHECK: struct A const &r = + // CHECK: A const &r = // CHECK: ImplicitCastExpr{{.*}}'struct A const' <NoOp> // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase> // CHECK: CXXMemberCallExpr{{.*}}'struct B' diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp index d9c5d014014a..6a039b93ebfa 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp @@ -51,10 +51,10 @@ void bind_lvalue_to_lvalue(Base b, Derived d, Base &br1 = b; Base &br2 = d; Derived &dr1 = d; - Derived &dr2 = b; // expected-error{{non-const lvalue reference to type 'struct Derived' cannot bind to a value of unrelated type 'struct Base'}} + Derived &dr2 = b; // expected-error{{non-const lvalue reference to type 'Derived' cannot bind to a value of unrelated type 'Base'}} Base &br3 = bc; // expected-error{{drops qualifiers}} Base &br4 = dc; // expected-error{{drops qualifiers}} - Base &br5 = diamond; // expected-error{{ambiguous conversion from derived class 'struct Diamond' to base class 'struct Base'}} + Base &br5 = diamond; // expected-error{{ambiguous conversion from derived class 'Diamond' to base class 'Base':}} int &ir = i; long &lr = i; // expected-error{{non-const lvalue reference to type 'long' cannot bind to a value of unrelated type 'int'}} } @@ -64,8 +64,8 @@ void bind_lvalue_quals(volatile Base b, volatile Derived d, volatile const int ivc) { volatile Base &bvr1 = b; volatile Base &bvr2 = d; - volatile Base &bvr3 = bvc; // expected-error{{binding of reference to type 'struct Base volatile' to a value of type 'struct Base const volatile' drops qualifiers}} - volatile Base &bvr4 = dvc; // expected-error{{binding of reference to type 'struct Base volatile' to a value of type 'struct Derived const volatile' drops qualifiers}} + volatile Base &bvr3 = bvc; // expected-error{{binding of reference to type 'Base volatile' to a value of type 'Base const volatile' drops qualifiers}} + volatile Base &bvr4 = dvc; // expected-error{{binding of reference to type 'Base volatile' to a value of type 'Derived const volatile' drops qualifiers}} volatile int &ir = ivc; // expected-error{{binding of reference to type 'int volatile' to a value of type 'int const volatile' drops qualifiers}} @@ -74,17 +74,17 @@ void bind_lvalue_quals(volatile Base b, volatile Derived d, } void bind_lvalue_to_rvalue() { - Base &br1 = Base(); // expected-error{{non-const lvalue reference to type 'struct Base' cannot bind to a temporary of type 'struct Base'}} - Base &br2 = Derived(); // expected-error{{non-const lvalue reference to type 'struct Base' cannot bind to a temporary of type 'struct Derived'}} - const volatile Base &br3 = Base(); // expected-error{{volatile lvalue reference to type 'struct Base const volatile' cannot bind to a temporary of type 'struct Base'}} - const volatile Base &br4 = Derived(); // expected-error{{volatile lvalue reference to type 'struct Base const volatile' cannot bind to a temporary of type 'struct Derived'}} + Base &br1 = Base(); // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a temporary of type 'Base'}} + Base &br2 = Derived(); // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a temporary of type 'Derived'}} + const volatile Base &br3 = Base(); // expected-error{{volatile lvalue reference to type 'Base const volatile' cannot bind to a temporary of type 'Base'}} + const volatile Base &br4 = Derived(); // expected-error{{volatile lvalue reference to type 'Base const volatile' cannot bind to a temporary of type 'Derived'}} int &ir = 17; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}} } void bind_lvalue_to_unrelated(Unrelated ur) { - Base &br1 = ur; // expected-error{{non-const lvalue reference to type 'struct Base' cannot bind to a value of unrelated type 'struct Unrelated'}} - const volatile Base &br2 = ur; // expected-error{{volatile lvalue reference to type 'struct Base const volatile' cannot bind to a value of unrelated type 'struct Unrelated'}} + Base &br1 = ur; // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a value of unrelated type 'Unrelated'}} + const volatile Base &br2 = ur; // expected-error{{volatile lvalue reference to type 'Base const volatile' cannot bind to a value of unrelated type 'Unrelated'}} } void bind_lvalue_to_conv_lvalue() { @@ -97,7 +97,7 @@ void bind_lvalue_to_conv_lvalue() { void bind_lvalue_to_conv_lvalue_ambig(ConvertibleToBothDerivedRef both) { Derived &dr1 = both; - Base &br1 = both; // expected-error{{reference initialization of type 'struct Base &' with initializer of type 'struct ConvertibleToBothDerivedRef' is ambiguous}} + Base &br1 = both; // expected-error{{reference initialization of type 'Base &' with initializer of type 'ConvertibleToBothDerivedRef' is ambiguous}} } struct IntBitfield { @@ -118,8 +118,8 @@ void bind_const_lvalue_to_rvalue() { const Base &br3 = create<const Base>(); const Base &br4 = create<const Derived>(); - const Base &br5 = create<const volatile Base>(); // expected-error{{binding of reference to type 'struct Base const' to a value of type 'struct Base const volatile' drops qualifiers}} - const Base &br6 = create<const volatile Derived>(); // expected-error{{binding of reference to type 'struct Base const' to a value of type 'struct Derived const volatile' drops qualifiers}} + const Base &br5 = create<const volatile Base>(); // expected-error{{binding of reference to type 'Base const' to a value of type 'Base const volatile' drops qualifiers}} + const Base &br6 = create<const volatile Derived>(); // expected-error{{binding of reference to type 'Base const' to a value of type 'Derived const volatile' drops qualifiers}} const int &ir = create<int>(); } @@ -131,5 +131,5 @@ void bind_const_lvalue_to_class_conv_temporary() { } void bind_lvalue_to_conv_rvalue_ambig(ConvertibleToBothDerived both) { const Derived &dr1 = both; - const Base &br1 = both; // expected-error{{reference initialization of type 'struct Base const &' with initializer of type 'struct ConvertibleToBothDerived' is ambiguous}} + const Base &br1 = both; // expected-error{{reference initialization of type 'Base const &' with initializer of type 'ConvertibleToBothDerived' is ambiguous}} } diff --git a/test/CXX/dcl.decl/dcl.init/p6.cpp b/test/CXX/dcl.decl/dcl.init/p6.cpp index f627a199eca6..c542dac1db1d 100644 --- a/test/CXX/dcl.decl/dcl.init/p6.cpp +++ b/test/CXX/dcl.decl/dcl.init/p6.cpp @@ -5,11 +5,12 @@ // If a program calls for the default initialization of an object of a // const-qualified type T, T shall be a class type with a // user-provided default constructor. -struct NoUserDefault { }; +struct MakeNonPOD { MakeNonPOD(); }; +struct NoUserDefault : public MakeNonPOD { }; struct HasUserDefault { HasUserDefault(); }; void test_const_default_init() { - const NoUserDefault x1; // expected-error{{default initialization of an object of const type 'struct NoUserDefault const' requires a user-provided default constructor}} + const NoUserDefault x1; // expected-error{{default initialization of an object of const type 'NoUserDefault const' requires a user-provided default constructor}} const HasUserDefault x2; const int x3; // expected-error{{default initialization of an object of const type 'int const'}} } diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp index 561e26b068f4..7e35788d898b 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp @@ -16,11 +16,11 @@ void f() { int b; A a(b); - int A::*ip = &A::s; // expected-error {{cannot initialize a variable of type 'int class A::*' with an rvalue of type 'int *'}} + int A::*ip = &A::s; // expected-error {{cannot initialize a variable of type 'int A::*' with an rvalue of type 'int *'}} a.*&A::s = 10; // expected-error{{right hand operand to .* has non pointer-to-member type 'int *'}} a.*&A::i = 10; // expected-error{{cannot form a pointer-to-member to member 'i' of reference type 'int &'}} - ft(a); // expected-note{{in instantiation of function template specialization 'ft<class A>' requested here}} + ft(a); // expected-note{{in instantiation of function template specialization 'ft<A>' requested here}} void A::*p = 0; // expected-error{{'p' declared as a member pointer to void}} } diff --git a/test/CodeCompletion/call.cpp b/test/CodeCompletion/call.cpp index 5467717bbc77..04d2a2f0c981 100644 --- a/test/CodeCompletion/call.cpp +++ b/test/CodeCompletion/call.cpp @@ -18,10 +18,10 @@ void f(); void test() { f(Y(), 0, 0); // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:19:9 %s -o - | FileCheck -check-prefix=CC1 %s - // CHECK-CC1: f(struct N::Y y, <#int ZZ#>) + // CHECK-CC1: f(N::Y y, <#int ZZ#>) // CHECK-CC1-NEXT: f(int i, <#int j#>, int k) // CHECK-CC1-NEXT: f(float x, <#float y#>) // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:19:13 %s -o - | FileCheck -check-prefix=CC2 %s - // CHECK-CC2-NOT: f(struct N::Y y, int ZZ) + // CHECK-CC2-NOT: f(N::Y y, int ZZ) // CHECK-CC2: f(int i, int j, <#int k#>) } diff --git a/test/CodeCompletion/enum-switch-case-qualified.cpp b/test/CodeCompletion/enum-switch-case-qualified.cpp index b9efcb43ed2b..e74ec9b5fe67 100644 --- a/test/CodeCompletion/enum-switch-case-qualified.cpp +++ b/test/CodeCompletion/enum-switch-case-qualified.cpp @@ -22,11 +22,11 @@ void test(enum N::C::Color color) { switch (color) { case // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:8 %s -o - | FileCheck -check-prefix=CC1 %s - // CHECK-CC1: Blue : [#enum M::N::C::Color#]N::C::Blue - // CHECK-CC1-NEXT: Green : [#enum M::N::C::Color#]N::C::Green - // CHECK-CC1-NEXT: Indigo : [#enum M::N::C::Color#]N::C::Indigo - // CHECK-CC1-NEXT: Orange : [#enum M::N::C::Color#]N::C::Orange - // CHECK-CC1-NEXT: Red : [#enum M::N::C::Color#]N::C::Red - // CHECK-CC1-NEXT: Violet : [#enum M::N::C::Color#]N::C::Violet - // CHECK-CC1: Yellow : [#enum M::N::C::Color#]N::C::Yellow + // CHECK-CC1: Blue : [#M::N::C::Color#]N::C::Blue + // CHECK-CC1-NEXT: Green : [#M::N::C::Color#]N::C::Green + // CHECK-CC1-NEXT: Indigo : [#M::N::C::Color#]N::C::Indigo + // CHECK-CC1-NEXT: Orange : [#M::N::C::Color#]N::C::Orange + // CHECK-CC1-NEXT: Red : [#M::N::C::Color#]N::C::Red + // CHECK-CC1-NEXT: Violet : [#M::N::C::Color#]N::C::Violet + // CHECK-CC1: Yellow : [#M::N::C::Color#]N::C::Yellow diff --git a/test/CodeCompletion/enum-switch-case.cpp b/test/CodeCompletion/enum-switch-case.cpp index 412f5f2f074d..2677f33f98f2 100644 --- a/test/CodeCompletion/enum-switch-case.cpp +++ b/test/CodeCompletion/enum-switch-case.cpp @@ -20,9 +20,9 @@ void test(enum N::Color color) { case // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:21:8 %s -o - | FileCheck -check-prefix=CC1 %s - // CHECK-CC1: Blue : [#enum N::Color#]N::Blue - // CHECK-CC1-NEXT: Green : [#enum N::Color#]N::Green - // CHECK-CC1-NEXT: Indigo : [#enum N::Color#]N::Indigo - // CHECK-CC1-NEXT: Orange : [#enum N::Color#]N::Orange - // CHECK-CC1-NEXT: Violet : [#enum N::Color#]N::Violet + // CHECK-CC1: Blue : [#N::Color#]N::Blue + // CHECK-CC1-NEXT: Green : [#N::Color#]N::Green + // CHECK-CC1-NEXT: Indigo : [#N::Color#]N::Indigo + // CHECK-CC1-NEXT: Orange : [#N::Color#]N::Orange + // CHECK-CC1-NEXT: Violet : [#N::Color#]N::Violet diff --git a/test/CodeGen/2010-03-09-DbgInfo.c b/test/CodeGen/2010-03-09-DbgInfo.c new file mode 100644 index 000000000000..04ee02e43719 --- /dev/null +++ b/test/CodeGen/2010-03-09-DbgInfo.c @@ -0,0 +1,2 @@ +// RUN: %clang -dA -S -O0 -g %s -o - | grep DW_TAG_variable +unsigned char ctable1[1] = { 0001 }; diff --git a/test/CodeGen/init.c b/test/CodeGen/init.c index f6b35361570a..13ffad173137 100644 --- a/test/CodeGen/init.c +++ b/test/CodeGen/init.c @@ -29,3 +29,14 @@ int f4() { static const int g4 = 12; return g4; } + +// PR6537 +typedef union vec3 { + struct { double x, y, z; }; + double component[3]; +} vec3; +vec3 f5(vec3 value) { + return (vec3) {{ + .x = value.x + }}; +} diff --git a/test/CodeGenCXX/2010-03-09-AnonAggregate.cpp b/test/CodeGenCXX/2010-03-09-AnonAggregate.cpp new file mode 100644 index 000000000000..99883d82636e --- /dev/null +++ b/test/CodeGenCXX/2010-03-09-AnonAggregate.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -g -S -o %t %s +// PR: 6554 +// More then one anonymous aggregates on one line creates chaos when MDNode uniquness is +// combined with RAUW operation. +// This test case causes crashes if malloc is configured to trip buffer overruns. +class MO { + + union { struct { union { int BA; } Val; int Offset; } OffsetedInfo; } Contents; + +}; + +class MO m; diff --git a/test/CodeGenCXX/PR6474.cpp b/test/CodeGenCXX/PR6474.cpp new file mode 100644 index 000000000000..68c09c9b95d5 --- /dev/null +++ b/test/CodeGenCXX/PR6474.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 %s -emit-llvm + +namespace test0 { +template <typename T> struct X { + virtual void foo(); + virtual void bar(); + virtual void baz(); +}; + +template <typename T> void X<T>::foo() {} +template <typename T> void X<T>::bar() {} +template <typename T> void X<T>::baz() {} + +template <> void X<char>::foo() {} +template <> void X<char>::bar() {} +} + +namespace test1 { +template <typename T> struct X { + virtual void foo(); + virtual void bar(); + virtual void baz(); +}; + +template <typename T> void X<T>::foo() {} +template <typename T> void X<T>::bar() {} +template <typename T> void X<T>::baz() {} + +template <> void X<char>::bar() {} +template <> void X<char>::foo() {} +} diff --git a/test/CodeGenCXX/default-destructor-nested.cpp b/test/CodeGenCXX/default-destructor-nested.cpp new file mode 100644 index 000000000000..86942743d4e1 --- /dev/null +++ b/test/CodeGenCXX/default-destructor-nested.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 %s -emit-llvm-only +// PR6294 + +class A { + virtual ~A(); +}; +class B { + class C; +}; +class B::C : public A { + C(); +}; +B::C::C() {} diff --git a/test/CodeGenCXX/internal-linkage.cpp b/test/CodeGenCXX/internal-linkage.cpp index 1ae0f08f86ee..4263891e57f5 100644 --- a/test/CodeGenCXX/internal-linkage.cpp +++ b/test/CodeGenCXX/internal-linkage.cpp @@ -1,11 +1,11 @@ // RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s -struct Global { }; -template<typename T> struct X { }; +struct Global { Global(); }; +template<typename T> struct X { X(); }; namespace { - struct Anon { }; + struct Anon { Anon(); }; // CHECK: @_ZN12_GLOBAL__N_15anon0E = internal global Global anon0; diff --git a/test/CodeGenCXX/mangle-system-header.cpp b/test/CodeGenCXX/mangle-system-header.cpp index cb68bc197600..6716b58926d7 100644 --- a/test/CodeGenCXX/mangle-system-header.cpp +++ b/test/CodeGenCXX/mangle-system-header.cpp @@ -5,3 +5,7 @@ # 1 "fake_system_header.h" 1 3 4 // CHECK: define void @_ZdlPvS_( void operator delete (void*, void*) {} + +// PR6217 +// CHECK: define void @_Z3barv() +void bar() { } diff --git a/test/CodeGenCXX/nullptr.cpp b/test/CodeGenCXX/nullptr.cpp index 31bd47522ed4..ab63b432bdfa 100644 --- a/test/CodeGenCXX/nullptr.cpp +++ b/test/CodeGenCXX/nullptr.cpp @@ -1,7 +1,17 @@ -// RUN: %clang_cc1 -std=c++0x %s -emit-llvm -o %t +// RUN: %clang_cc1 -std=c++0x -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s int* a = nullptr; void f() { int* a = nullptr; } + +typedef decltype(nullptr) nullptr_t; + +nullptr_t get_nullptr(); + +struct X { }; +void g() { + // CHECK: call i8* @_Z11get_nullptrv() + int (X::*pmf)(int) = get_nullptr(); +} diff --git a/test/CodeGenCXX/virtual-base-destructor-call.cpp b/test/CodeGenCXX/virtual-base-destructor-call.cpp index b6e85e208b15..7de9dd2a6085 100644 --- a/test/CodeGenCXX/virtual-base-destructor-call.cpp +++ b/test/CodeGenCXX/virtual-base-destructor-call.cpp @@ -22,6 +22,11 @@ int main() { // CHECK: call void @_ZN14basic_iostreamIcED2Ev // CHECK: call void @_ZN9basic_iosD2Ev +// basic_iostream's base dtor calls its non-virtual base dtor. +// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED2Ev +// CHECK: call void @_ZN13basic_istreamIcED2Ev +// CHECK: } + // basic_iostream's deleting dtor calls its complete dtor, then // operator delete(). // CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED0Ev @@ -40,11 +45,6 @@ int main() { // CHECK: call void @_ZN13basic_istreamIcED1Ev // CHECK: call void @_ZdlPv -// basic_iostream's base dtor calls its non-virtual base dtor. -// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED2Ev -// CHECK: call void @_ZN13basic_istreamIcED2Ev -// CHECK: } - // basic_istream's base dtor is a no-op. // CHECK: define linkonce_odr void @_ZN13basic_istreamIcED2Ev // CHECK-NOT: call diff --git a/test/CodeGenCXX/vtable-layout-abi-examples.cpp b/test/CodeGenCXX/vtable-layout-abi-examples.cpp index 2c6b7a48ccfe..a82fca736c79 100644 --- a/test/CodeGenCXX/vtable-layout-abi-examples.cpp +++ b/test/CodeGenCXX/vtable-layout-abi-examples.cpp @@ -187,3 +187,126 @@ struct D : public B, public C { void D::d() { } } + +namespace Test3 { + +// From http://www.codesourcery.com/public/cxx-abi/abi-examples.html#vtable-ctor + +struct V1 { + int v1; + virtual void f(); +}; + +struct V2 : virtual V1 { + int v2; + virtual void f(); +}; + +// CHECK: Vtable for 'Test3::C' (14 entries). +// CHECK-NEXT: 0 | vbase_offset (32) +// CHECK-NEXT: 1 | vbase_offset (16) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test3::C RTTI +// CHECK-NEXT: -- (Test3::C, 0) vtable address -- +// CHECK-NEXT: 4 | void Test3::C::f() +// CHECK-NEXT: 5 | vcall_offset (-16) +// CHECK-NEXT: 6 | offset_to_top (-16) +// CHECK-NEXT: 7 | Test3::C RTTI +// CHECK-NEXT: -- (Test3::V1, 16) vtable address -- +// CHECK-NEXT: 8 | void Test3::C::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-NEXT: 9 | vcall_offset (-32) +// CHECK-NEXT: 10 | vbase_offset (-16) +// CHECK-NEXT: 11 | offset_to_top (-32) +// CHECK-NEXT: 12 | Test3::C RTTI +// CHECK-NEXT: -- (Test3::V2, 32) vtable address -- +// CHECK-NEXT: 13 | void Test3::C::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] + +// CHECK: Construction vtable for ('Test3::V2', 32) in 'Test3::C' (9 entries). +// CHECK-NEXT: 0 | vcall_offset (0) +// CHECK-NEXT: 1 | vbase_offset (-16) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test3::V2 RTTI +// CHECK-NEXT: -- (Test3::V2, 32) vtable address -- +// CHECK-NEXT: 4 | void Test3::V2::f() +// CHECK-NEXT: 5 | vcall_offset (16) +// CHECK-NEXT: 6 | offset_to_top (16) +// CHECK-NEXT: 7 | Test3::V2 RTTI +// CHECK-NEXT: -- (Test3::V1, 16) vtable address -- +// CHECK-NEXT: 8 | void Test3::V2::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +struct C : virtual V1, virtual V2 { + int c; + virtual void f(); +}; +void C::f() { } + +struct B { + int b; +}; + +// CHECK: Vtable for 'Test3::D' (15 entries). +// CHECK-NEXT: 0 | vbase_offset (40) +// CHECK-NEXT: 1 | vbase_offset (24) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test3::D RTTI +// CHECK-NEXT: -- (Test3::C, 0) vtable address -- +// CHECK-NEXT: -- (Test3::D, 0) vtable address -- +// CHECK-NEXT: 4 | void Test3::C::f() +// CHECK-NEXT: 5 | void Test3::D::g() +// CHECK-NEXT: 6 | vcall_offset (-24) +// CHECK-NEXT: 7 | offset_to_top (-24) +// CHECK-NEXT: 8 | Test3::D RTTI +// CHECK-NEXT: -- (Test3::V1, 24) vtable address -- +// CHECK-NEXT: 9 | void Test3::C::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-NEXT: 10 | vcall_offset (-40) +// CHECK-NEXT: 11 | vbase_offset (-16) +// CHECK-NEXT: 12 | offset_to_top (-40) +// CHECK-NEXT: 13 | Test3::D RTTI +// CHECK-NEXT: -- (Test3::V2, 40) vtable address -- +// CHECK-NEXT: 14 | void Test3::C::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] + +// CHECK: Construction vtable for ('Test3::C', 0) in 'Test3::D' (14 entries). +// CHECK-NEXT: 0 | vbase_offset (40) +// CHECK-NEXT: 1 | vbase_offset (24) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test3::C RTTI +// CHECK-NEXT: -- (Test3::C, 0) vtable address -- +// CHECK-NEXT: 4 | void Test3::C::f() +// CHECK-NEXT: 5 | vcall_offset (-24) +// CHECK-NEXT: 6 | offset_to_top (-24) +// CHECK-NEXT: 7 | Test3::C RTTI +// CHECK-NEXT: -- (Test3::V1, 24) vtable address -- +// CHECK-NEXT: 8 | void Test3::C::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-NEXT: 9 | vcall_offset (-40) +// CHECK-NEXT: 10 | vbase_offset (-16) +// CHECK-NEXT: 11 | offset_to_top (-40) +// CHECK-NEXT: 12 | Test3::C RTTI +// CHECK-NEXT: -- (Test3::V2, 40) vtable address -- +// CHECK-NEXT: 13 | void Test3::C::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] + +// CHECK: Construction vtable for ('Test3::V2', 40) in 'Test3::D' (9 entries). +// CHECK-NEXT: 0 | vcall_offset (0) +// CHECK-NEXT: 1 | vbase_offset (-16) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test3::V2 RTTI +// CHECK-NEXT: -- (Test3::V2, 40) vtable address -- +// CHECK-NEXT: 4 | void Test3::V2::f() +// CHECK-NEXT: 5 | vcall_offset (16) +// CHECK-NEXT: 6 | offset_to_top (16) +// CHECK-NEXT: 7 | Test3::V2 RTTI +// CHECK-NEXT: -- (Test3::V1, 24) vtable address -- +// CHECK-NEXT: 8 | void Test3::V2::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +struct D : B, C { + int d; + virtual void g(); +}; +void D::g() { } + +} diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index a65af6ed33da..5c783f1f23dc 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -1036,3 +1036,58 @@ struct C : A, virtual V, B { void C::g() { } } + +namespace Test26 { + +// Test that we generate the right number of entries in the C-in-D construction vtable, and that +// we don't mark A::a as unused. + +struct A { + virtual void a(); +}; + +struct B { + virtual void c(); +}; + +struct C : virtual A { + virtual void b(); +}; + +// CHECK: Vtable for 'Test26::D' (15 entries). +// CHECK-NEXT: 0 | vbase_offset (8) +// CHECK-NEXT: 1 | vbase_offset (8) +// CHECK-NEXT: 2 | vbase_offset (0) +// CHECK-NEXT: 3 | vcall_offset (0) +// CHECK-NEXT: 4 | offset_to_top (0) +// CHECK-NEXT: 5 | Test26::D RTTI +// CHECK-NEXT: -- (Test26::B, 0) vtable address -- +// CHECK-NEXT: -- (Test26::D, 0) vtable address -- +// CHECK-NEXT: 6 | void Test26::B::c() +// CHECK-NEXT: 7 | void Test26::D::d() +// CHECK-NEXT: 8 | vcall_offset (0) +// CHECK-NEXT: 9 | vbase_offset (0) +// CHECK-NEXT: 10 | vcall_offset (0) +// CHECK-NEXT: 11 | offset_to_top (-8) +// CHECK-NEXT: 12 | Test26::D RTTI +// CHECK-NEXT: -- (Test26::A, 8) vtable address -- +// CHECK-NEXT: -- (Test26::C, 8) vtable address -- +// CHECK-NEXT: 13 | void Test26::A::a() +// CHECK-NEXT: 14 | void Test26::C::b() + +// CHECK: Construction vtable for ('Test26::C', 8) in 'Test26::D' (7 entries). +// CHECK-NEXT: 0 | vcall_offset (0) +// CHECK-NEXT: 1 | vbase_offset (0) +// CHECK-NEXT: 2 | vcall_offset (0) +// CHECK-NEXT: 3 | offset_to_top (0) +// CHECK-NEXT: 4 | Test26::C RTTI +// CHECK-NEXT: -- (Test26::A, 8) vtable address -- +// CHECK-NEXT: -- (Test26::C, 8) vtable address -- +// CHECK-NEXT: 5 | void Test26::A::a() +// CHECK-NEXT: 6 | void Test26::C::b() +class D : virtual B, virtual C { + virtual void d(); +}; +void D::d() { } + +} diff --git a/test/CodeGenObjC/id-isa-codegen.m b/test/CodeGenObjC/id-isa-codegen.m index e893aaa4f3c2..e4f5fd9ab571 100644 --- a/test/CodeGenObjC/id-isa-codegen.m +++ b/test/CodeGenObjC/id-isa-codegen.m @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck -check-prefix LP64 %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm -o - %s | FileCheck -check-prefix LP32 %s typedef struct objc_class *Class; @@ -63,4 +64,10 @@ id Test2() { ((id)cat)->isa = dynamicSubclass; } @end +// CHECK-LP64: %{{.*}} = load i8** % +// CHECK-NEXT: %{{.*}} = bitcast i8* %{{.*}} to i8** +// CHECK-NEXT: store i8* %{{.*}}, i8** %{{.*}} +// CHECK-LP32: %{{.*}} = load i8** % +// CHECK-NEXT: %{{.*}} = bitcast i8* %{{.*}} to i8** +// CHECK-NEXT: store i8* %{{.*}}, i8** %{{.*}} diff --git a/test/Driver/clang-g-opts.c b/test/Driver/clang-g-opts.c new file mode 100644 index 000000000000..4dbdf6167734 --- /dev/null +++ b/test/Driver/clang-g-opts.c @@ -0,0 +1,5 @@ +// RUN: %clang -S -v -o %t %s 2>&1 | not grep -w -- -g +// RUN: %clang -S -v -o %t %s -g 2>&1 | grep -w -- -g +// RUN: %clang -S -v -o %t %s -g0 2>&1 | not grep -w -- -g +// RUN: %clang -S -v -o %t %s -g -g0 2>&1 | not grep -w -- -g +// RUN: %clang -S -v -o %t %s -g0 -g 2>&1 | grep -w -- -g diff --git a/test/FixIt/typo.cpp b/test/FixIt/typo.cpp index c0570258c53b..efc9ba890c6f 100644 --- a/test/FixIt/typo.cpp +++ b/test/FixIt/typo.cpp @@ -31,12 +31,12 @@ bool test_string(std::string s) { std::basic_sting<char> b2; // expected-error{{no template named 'basic_sting' in namespace 'std'; did you mean 'basic_string'?}} (void)b1; (void)b2; - return s.fnd("hello") // expected-error{{no member named 'fnd' in 'class std::basic_string<char>'; did you mean 'find'?}} - == std::string::pos; // expected-error{{no member named 'pos' in 'class std::basic_string<char>'; did you mean 'npos'?}} + return s.fnd("hello") // expected-error{{no member named 'fnd' in 'std::basic_string<char>'; did you mean 'find'?}} + == std::string::pos; // expected-error{{no member named 'pos' in 'std::basic_string<char>'; did you mean 'npos'?}} } struct Base { }; -struct Derived : public Base { // expected-note{{base class 'struct Base' specified here}} +struct Derived : public Base { // expected-note{{base class 'Base' specified here}} int member; // expected-note 3{{'member' declared here}} Derived() : base(), // expected-error{{initializer 'base' does not name a non-static data member or base class; did you mean the base class 'Base'?}} diff --git a/test/Headers/typedef_guards.c b/test/Headers/typedef_guards.c new file mode 100644 index 000000000000..1aa667bb7e04 --- /dev/null +++ b/test/Headers/typedef_guards.c @@ -0,0 +1,28 @@ +// RUN: %clang -fsyntax-only -verify %s + +// NULL is rdefined in stddef.h +#define NULL ((void*) 0) + +// These are headers bundled with Clang. +#include <stdarg.h> +#include <stddef.h> + +#ifndef _VA_LIST +typedef __builtin_va_list va_list; +#endif + +#ifndef _SIZE_T +typedef __typeof__(sizeof(int)) size_t; +#endif + +#ifndef _WCHAR_T +typedef __typeof__(*L"") wchar_t; +#endif + +extern void foo(wchar_t x); +extern void bar(size_t x); +void *baz() { return NULL; } +void quz() { + va_list y; +} + diff --git a/test/Index/annotate-tokens.m b/test/Index/annotate-tokens.m new file mode 100644 index 000000000000..1badeb20be79 --- /dev/null +++ b/test/Index/annotate-tokens.m @@ -0,0 +1,49 @@ +@interface Foo +- (int)compare:(Foo*)other; +@end + +@implementation Foo +- (int)compare:(Foo*)other { + return 0; +} +@end + +// RUN: c-index-test -test-annotate-tokens=%s:1:1:9:5 %s | FileCheck %s +// CHECK: Punctuation: "@" [1:1 - 1:2] +// CHECK: Identifier: "interface" [1:2 - 1:11] +// CHECK: Identifier: "Foo" [1:12 - 1:15] ObjCInterfaceDecl=Foo:1:12 +// CHECK: Punctuation: "-" [2:1 - 2:2] ObjCInstanceMethodDecl=compare::2:1 +// CHECK: Punctuation: "(" [2:3 - 2:4] +// CHECK: Keyword: "int" [2:4 - 2:7] +// CHECK: Punctuation: ")" [2:7 - 2:8] +// CHECK: Identifier: "compare" [2:8 - 2:15] +// CHECK: Punctuation: ":" [2:15 - 2:16] +// CHECK: Punctuation: "(" [2:16 - 2:17] +// CHECK: Identifier: "Foo" [2:17 - 2:20] ObjCClassRef=Foo:1:12 +// CHECK: Punctuation: "*" [2:20 - 2:21] +// CHECK: Punctuation: ")" [2:21 - 2:22] +// CHECK: Identifier: "other" [2:22 - 2:27] ParmDecl=other:2:22 (Definition) +// CHECK: Punctuation: ";" [2:27 - 2:28] +// CHECK: Punctuation: "@" [3:1 - 3:2] +// CHECK: Identifier: "end" [3:2 - 3:5] +// CHECK: Punctuation: "@" [5:1 - 5:2] ObjCImplementationDecl=Foo:5:1 (Definition) +// CHECK: Identifier: "implementation" [5:2 - 5:16] +// CHECK: Identifier: "Foo" [5:17 - 5:20] +// CHECK: Punctuation: "-" [6:1 - 6:2] ObjCInstanceMethodDecl=compare::6:1 (Definition) +// CHECK: Punctuation: "(" [6:3 - 6:4] +// CHECK: Keyword: "int" [6:4 - 6:7] +// CHECK: Punctuation: ")" [6:7 - 6:8] +// CHECK: Identifier: "compare" [6:8 - 6:15] +// CHECK: Punctuation: ":" [6:15 - 6:16] +// CHECK: Punctuation: "(" [6:16 - 6:17] +// CHECK: Identifier: "Foo" [6:17 - 6:20] ObjCClassRef=Foo:1:12 +// CHECK: Punctuation: "*" [6:20 - 6:21] +// CHECK: Punctuation: ")" [6:21 - 6:22] +// CHECK: Identifier: "other" [6:22 - 6:27] ParmDecl=other:6:22 (Definition) +// CHECK: Punctuation: "{" [6:28 - 6:29] +// CHECK: Keyword: "return" [7:3 - 7:9] +// CHECK: Literal: "0" [7:10 - 7:11] +// CHECK: Punctuation: ";" [7:11 - 7:12] +// CHECK: Punctuation: "}" [8:1 - 8:2] +// CHECK: Punctuation: "@" [9:1 - 9:2] +// CHECK: Identifier: "end" [9:2 - 9:5] diff --git a/test/Index/c-index-getCursor-test.m b/test/Index/c-index-getCursor-test.m index 6a17e1c8417a..8341b80a673f 100644 --- a/test/Index/c-index-getCursor-test.m +++ b/test/Index/c-index-getCursor-test.m @@ -90,7 +90,9 @@ int main (int argc, const char * argv[]) { // CHECK: [31:27 - 33:9] ObjCInterfaceDecl=Baz:31:12 // CHECK: [33:9 - 33:16] ObjCIvarDecl=_anIVar:33:9 (Definition) // CHECK: [33:16 - 36:1] ObjCInterfaceDecl=Baz:31:12 -// CHECK: [36:1 - 36:21] ObjCInstanceMethodDecl=bazMethod:36:1 +// CHECK: [36:1 - 36:4] ObjCInstanceMethodDecl=bazMethod:36:1 +// CHECK: [36:4 - 36:7] ObjCClassRef=Foo:3:12 +// CHECK: [36:7 - 36:21] ObjCInstanceMethodDecl=bazMethod:36:1 // CHECK: [36:21 - 38:5] ObjCInterfaceDecl=Baz:31:12 // CHECK: [38:5 - 40:1] Invalid Cursor => NoDeclFound // CHECK: [40:1 - 41:3] EnumDecl=:40:1 (Definition) @@ -118,7 +120,9 @@ int main (int argc, const char * argv[]) { // CHECK: [47:4 - 47:6] VarDecl=c:47:12 (Definition) // CHECK: [47:6 - 47:10] ObjCProtocolRef=SubP:27:1 // CHECK: [47:10 - 47:16] VarDecl=c:47:12 (Definition) -// CHECK: [47:16 - 47:26] ObjCMessageExpr=fooC:8:1 +// CHECK: [47:16 - 47:17] ObjCMessageExpr=fooC:8:1 +// CHECK: [47:17 - 47:20] ObjCClassRef=Foo:3:12 +// CHECK: [47:20 - 47:26] ObjCMessageExpr=fooC:8:1 // CHECK: [47:26 - 47:27] UnexposedStmt= // CHECK: [47:27 - 48:2] UnexposedStmt= // CHECK: [48:2 - 48:4] TypeRef=id:0:0 diff --git a/test/Index/code-completion.cpp b/test/Index/code-completion.cpp index 7fd4376735a0..670b13f6344b 100644 --- a/test/Index/code-completion.cpp +++ b/test/Index/code-completion.cpp @@ -38,10 +38,10 @@ void test_overloaded() { // CHECK-MEMBER: FieldDecl:{ResultType float}{Text Y::}{TypedText member} // CHECK-MEMBER: FunctionDecl:{ResultType void}{Informative Y::}{TypedText memfunc}{LeftParen (}{Optional {Placeholder int i}}{RightParen )} // CHECK-MEMBER: FunctionDecl:{ResultType int}{TypedText operator int}{LeftParen (}{RightParen )}{Informative const} -// CHECK-MEMBER: FunctionDecl:{ResultType struct Z &}{TypedText operator=}{LeftParen (}{Placeholder struct Z const &}{RightParen )} -// CHECK-MEMBER: FunctionDecl:{ResultType struct X &}{Text X::}{TypedText operator=}{LeftParen (}{Placeholder struct X const &}{RightParen )} -// CHECK-MEMBER: FunctionDecl:{ResultType struct Y &}{Text Y::}{TypedText operator=}{LeftParen (}{Placeholder struct Y const &}{RightParen )} -// CHECK-MEMBER: EnumConstantDecl:{ResultType enum X::E}{Informative E::}{TypedText Val1} +// CHECK-MEMBER: FunctionDecl:{ResultType Z &}{TypedText operator=}{LeftParen (}{Placeholder Z const &}{RightParen )} +// CHECK-MEMBER: FunctionDecl:{ResultType X &}{Text X::}{TypedText operator=}{LeftParen (}{Placeholder X const &}{RightParen )} +// CHECK-MEMBER: FunctionDecl:{ResultType Y &}{Text Y::}{TypedText operator=}{LeftParen (}{Placeholder Y const &}{RightParen )} +// CHECK-MEMBER: EnumConstantDecl:{ResultType X::E}{Informative E::}{TypedText Val1} // CHECK-MEMBER: StructDecl:{TypedText X}{Text ::} // CHECK-MEMBER: StructDecl:{TypedText Y}{Text ::} // CHECK-MEMBER: StructDecl:{TypedText Z}{Text ::} @@ -49,6 +49,6 @@ void test_overloaded() { // CHECK-MEMBER: FunctionDecl:{ResultType void}{Informative Y::}{TypedText ~Y}{LeftParen (}{RightParen )} // CHECK-MEMBER: FunctionDecl:{ResultType void}{TypedText ~Z}{LeftParen (}{RightParen )} -// CHECK-OVERLOAD: NotImplemented:{ResultType int &}{Text overloaded}{LeftParen (}{Text struct Z z}{Comma , }{CurrentParameter int second}{RightParen )} +// CHECK-OVERLOAD: NotImplemented:{ResultType int &}{Text overloaded}{LeftParen (}{Text Z z}{Comma , }{CurrentParameter int second}{RightParen )} // CHECK-OVERLOAD: NotImplemented:{ResultType float &}{Text overloaded}{LeftParen (}{Text int i}{Comma , }{CurrentParameter long second}{RightParen )} // CHECK-OVERLOAD: NotImplemented:{ResultType double &}{Text overloaded}{LeftParen (}{Text float f}{Comma , }{CurrentParameter int second}{RightParen )} diff --git a/test/Parser/altivec.c b/test/Parser/altivec.c index 99544ea5c103..c2a32cfa390e 100644 --- a/test/Parser/altivec.c +++ b/test/Parser/altivec.c @@ -41,28 +41,28 @@ void f_a(vector int a); void f_a2(int b, vector int a); // These should have warnings. -__vector long vv_l; // expected-warning {{Use of "long" with "__vector" is deprecated}} -__vector signed long vv_sl; // expected-warning {{Use of "long" with "__vector" is deprecated}} -__vector unsigned long vv_ul; // expected-warning {{Use of "long" with "__vector" is deprecated}} -__vector long int vv_li; // expected-warning {{Use of "long" with "__vector" is deprecated}} -__vector signed long int vv_sli; // expected-warning {{Use of "long" with "__vector" is deprecated}} -__vector unsigned long int vv_uli; // expected-warning {{Use of "long" with "__vector" is deprecated}} -vector long v_l; // expected-warning {{Use of "long" with "__vector" is deprecated}} -vector signed long v_sl; // expected-warning {{Use of "long" with "__vector" is deprecated}} -vector unsigned long v_ul; // expected-warning {{Use of "long" with "__vector" is deprecated}} -vector long int v_li; // expected-warning {{Use of "long" with "__vector" is deprecated}} -vector signed long int v_sli; // expected-warning {{Use of "long" with "__vector" is deprecated}} -vector unsigned long int v_uli; // expected-warning {{Use of "long" with "__vector" is deprecated}} -__vector long double vv_ld; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} -vector long double v_ld; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} +__vector long vv_l; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +__vector signed long vv_sl; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +__vector unsigned long vv_ul; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +__vector long int vv_li; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +__vector signed long int vv_sli; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +__vector unsigned long int vv_uli; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +vector long v_l; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +vector signed long v_sl; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +vector unsigned long v_ul; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +vector long int v_li; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +vector signed long int v_sli; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +vector unsigned long int v_uli; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +__vector long double vv_ld; // expected-warning {{Use of 'long' with '__vector' is deprecated}} expected-error {{cannot use 'double' with '__vector'}} +vector long double v_ld; // expected-warning {{Use of 'long' with '__vector' is deprecated}} expected-error {{cannot use 'double' with '__vector'}} // These should have errors. -__vector double vv_d; // expected-error {{cannot use "double" with "__vector"}} -__vector double vv_d; // expected-error {{cannot use "double" with "__vector"}} -vector double v_d; // expected-error {{cannot use "double" with "__vector"}} -vector double v_d; // expected-error {{cannot use "double" with "__vector"}} -__vector long double vv_ld; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} -vector long double v_ld; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} +__vector double vv_d; // expected-error {{cannot use 'double' with '__vector'}} +__vector double vv_d; // expected-error {{cannot use 'double' with '__vector'}} +vector double v_d; // expected-error {{cannot use 'double' with '__vector'}} +vector double v_d; // expected-error {{cannot use 'double' with '__vector'}} +__vector long double vv_ld; // expected-warning {{Use of 'long' with '__vector' is deprecated}} expected-error {{cannot use 'double' with '__vector'}} +vector long double v_ld; // expected-warning {{Use of 'long' with '__vector' is deprecated}} expected-error {{cannot use 'double' with '__vector'}} void f() { __vector unsigned int v = {0,0,0,0}; diff --git a/test/Parser/cxx-altivec.cpp b/test/Parser/cxx-altivec.cpp index a26eee4ef487..3610c0e04930 100644 --- a/test/Parser/cxx-altivec.cpp +++ b/test/Parser/cxx-altivec.cpp @@ -43,26 +43,26 @@ void f_a(vector int a); void f_a2(int b, vector int a); // These should have warnings. -__vector long vv_l; // expected-warning {{Use of "long" with "__vector" is deprecated}} -__vector signed long vv_sl; // expected-warning {{Use of "long" with "__vector" is deprecated}} -__vector unsigned long vv_ul; // expected-warning {{Use of "long" with "__vector" is deprecated}} -__vector long int vv_li; // expected-warning {{Use of "long" with "__vector" is deprecated}} -__vector signed long int vv_sli; // expected-warning {{Use of "long" with "__vector" is deprecated}} -__vector unsigned long int vv_uli; // expected-warning {{Use of "long" with "__vector" is deprecated}} -vector long v_l; // expected-warning {{Use of "long" with "__vector" is deprecated}} -vector signed long v_sl; // expected-warning {{Use of "long" with "__vector" is deprecated}} -vector unsigned long v_ul; // expected-warning {{Use of "long" with "__vector" is deprecated}} -vector long int v_li; // expected-warning {{Use of "long" with "__vector" is deprecated}} -vector signed long int v_sli; // expected-warning {{Use of "long" with "__vector" is deprecated}} -vector unsigned long int v_uli; // expected-warning {{Use of "long" with "__vector" is deprecated}} -__vector long double vv_ld; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} -vector long double v_ld; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} +__vector long vv_l; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +__vector signed long vv_sl; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +__vector unsigned long vv_ul; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +__vector long int vv_li; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +__vector signed long int vv_sli; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +__vector unsigned long int vv_uli; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +vector long v_l; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +vector signed long v_sl; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +vector unsigned long v_ul; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +vector long int v_li; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +vector signed long int v_sli; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +vector unsigned long int v_uli; // expected-warning {{Use of 'long' with '__vector' is deprecated}} +__vector long double vv_ld; // expected-warning {{Use of 'long' with '__vector' is deprecated}} expected-error {{cannot use 'double' with '__vector'}} +vector long double v_ld; // expected-warning {{Use of 'long' with '__vector' is deprecated}} expected-error {{cannot use 'double' with '__vector'}} // These should have errors. -__vector double vv_d1; // expected-error {{cannot use "double" with "__vector"}} -vector double v_d2; // expected-error {{cannot use "double" with "__vector"}} -__vector long double vv_ld3; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} -vector long double v_ld4; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} +__vector double vv_d1; // expected-error {{cannot use 'double' with '__vector'}} +vector double v_d2; // expected-error {{cannot use 'double' with '__vector'}} +__vector long double vv_ld3; // expected-warning {{Use of 'long' with '__vector' is deprecated}} expected-error {{cannot use 'double' with '__vector'}} +vector long double v_ld4; // expected-warning {{Use of 'long' with '__vector' is deprecated}} expected-error {{cannot use 'double' with '__vector'}} void f() { __vector unsigned int v = {0,0,0,0}; diff --git a/test/Sema/warn-missing-braces.c b/test/Sema/warn-missing-braces.c new file mode 100644 index 000000000000..07eb61aac003 --- /dev/null +++ b/test/Sema/warn-missing-braces.c @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -fsyntax-only -Wmissing-braces -verify %s + +int a[2][2] = { 0, 1, 2, 3 }; // expected-warning{{suggest braces}} expected-warning{{suggest braces}}
\ No newline at end of file diff --git a/test/SemaCXX/access-base-class.cpp b/test/SemaCXX/access-base-class.cpp index d0b0fb8ee223..eeb5f1c86fc3 100644 --- a/test/SemaCXX/access-base-class.cpp +++ b/test/SemaCXX/access-base-class.cpp @@ -5,7 +5,7 @@ class A { }; class B : private A { }; // expected-note {{declared private here}} void f(B* b) { - A *a = b; // expected-error{{cannot cast 'class T1::B' to its private base class 'class T1::A'}} + A *a = b; // expected-error{{cannot cast 'T1::B' to its private base class 'T1::A'}} } } @@ -16,7 +16,7 @@ class A { }; class B : A { }; // expected-note {{implicitly declared private here}} void f(B* b) { - A *a = b; // expected-error {{cannot cast 'class T2::B' to its private base class 'class T2::A'}} + A *a = b; // expected-error {{cannot cast 'T2::B' to its private base class 'T2::A'}} } } @@ -69,7 +69,7 @@ namespace T6 { class C : public B { void f(C *c) { - A* a = c; // expected-error {{cannot cast 'class T6::C' to its private base class 'class T6::A'}} + A* a = c; // expected-error {{cannot cast 'T6::C' to its private base class 'T6::A'}} } }; diff --git a/test/SemaCXX/access-control-check.cpp b/test/SemaCXX/access-control-check.cpp index 783d4def5327..1db6704909df 100644 --- a/test/SemaCXX/access-control-check.cpp +++ b/test/SemaCXX/access-control-check.cpp @@ -11,5 +11,5 @@ class P { class N : M,P { N() {} - int PR() { return iP + PPR(); } // expected-error 2 {{private member of 'class P'}} + int PR() { return iP + PPR(); } // expected-error 2 {{private member of 'P'}} }; diff --git a/test/SemaCXX/aggregate-initialization.cpp b/test/SemaCXX/aggregate-initialization.cpp index 83f4179d9136..708a8f256a3d 100644 --- a/test/SemaCXX/aggregate-initialization.cpp +++ b/test/SemaCXX/aggregate-initialization.cpp @@ -22,10 +22,10 @@ struct NonAggr4 { virtual void f(); }; -NonAggr1 na1 = { 17 }; // expected-error{{non-aggregate type 'struct NonAggr1' cannot be initialized with an initializer list}} -NonAggr2 na2 = { 17 }; // expected-error{{non-aggregate type 'struct NonAggr2' cannot be initialized with an initializer list}} -NonAggr3 na3 = { 17 }; // expected-error{{non-aggregate type 'class NonAggr3' cannot be initialized with an initializer list}} -NonAggr4 na4 = { 17 }; // expected-error{{non-aggregate type 'struct NonAggr4' cannot be initialized with an initializer list}} +NonAggr1 na1 = { 17 }; // expected-error{{non-aggregate type 'NonAggr1' cannot be initialized with an initializer list}} +NonAggr2 na2 = { 17 }; // expected-error{{non-aggregate type 'NonAggr2' cannot be initialized with an initializer list}} +NonAggr3 na3 = { 17 }; // expected-error{{non-aggregate type 'NonAggr3' cannot be initialized with an initializer list}} +NonAggr4 na4 = { 17 }; // expected-error{{non-aggregate type 'NonAggr4' cannot be initialized with an initializer list}} // PR5817 typedef int type[][2]; @@ -60,10 +60,10 @@ struct C { void f() { A as1[1] = { }; - A as2[1] = { 1 }; // expected-error {{copying array element of type 'struct A' invokes deleted copy constructor}} + A as2[1] = { 1 }; // expected-error {{copying array element of type 'A' invokes deleted copy constructor}} B b1 = { }; - B b2 = { 1 }; // expected-error {{copying member subobject of type 'struct A' invokes deleted copy constructor}} + B b2 = { 1 }; // expected-error {{copying member subobject of type 'A' invokes deleted copy constructor}} C c1 = { 1 }; } diff --git a/test/SemaCXX/ambig-user-defined-conversions.cpp b/test/SemaCXX/ambig-user-defined-conversions.cpp index 5e0a2e3766f8..7f676748740c 100644 --- a/test/SemaCXX/ambig-user-defined-conversions.cpp +++ b/test/SemaCXX/ambig-user-defined-conversions.cpp @@ -19,7 +19,7 @@ namespace test0 { const int Test1() { func(b1, f()); // expected-error {{call to 'func' is ambiguous}} - return f(); // expected-error {{conversion from 'struct test0::B' to 'int const' is ambiguous}} + return f(); // expected-error {{conversion from 'test0::B' to 'int const' is ambiguous}} } // This used to crash when comparing the two operands. diff --git a/test/SemaCXX/arrow-operator.cpp b/test/SemaCXX/arrow-operator.cpp index fd1ec0120a71..29b23edad3a1 100644 --- a/test/SemaCXX/arrow-operator.cpp +++ b/test/SemaCXX/arrow-operator.cpp @@ -16,7 +16,7 @@ struct C : A, B { struct D : A { }; -struct E; // expected-note {{forward declaration of 'struct E'}} +struct E; // expected-note {{forward declaration of 'E'}} void f(C &c, D& d, E& e) { c->f(); // expected-error{{use of overloaded operator '->' is ambiguous}} diff --git a/test/SemaCXX/attr-cxx0x.cpp b/test/SemaCXX/attr-cxx0x.cpp index 9924d1bc5707..8fbf50c26ec1 100644 --- a/test/SemaCXX/attr-cxx0x.cpp +++ b/test/SemaCXX/attr-cxx0x.cpp @@ -2,7 +2,7 @@ int final_fail [[final]]; //expected-error {{'final' attribute only applies to virtual method or class types}} -struct [[final]] final_base { }; // expected-note {{'struct final_base' declared here}} +struct [[final]] final_base { }; // expected-note {{'final_base' declared here}} struct final_child : final_base { }; // expected-error {{derivation from 'final' struct final_base}} struct final_member { virtual void quux [[final]] (); }; // expected-note {{overridden virtual function is here}} diff --git a/test/SemaCXX/builtin-ptrtomember-overload-1.cpp b/test/SemaCXX/builtin-ptrtomember-overload-1.cpp index b1b0b98b3c06..f736394a4caa 100644 --- a/test/SemaCXX/builtin-ptrtomember-overload-1.cpp +++ b/test/SemaCXX/builtin-ptrtomember-overload-1.cpp @@ -41,6 +41,6 @@ void foo1(C1 c1, int A::* pmf) { void foo1(C1 c1, int E::* pmf) { int i = c1->*pmf; // expected-error {{use of overloaded operator '->*' is ambiguous}} \ - // expected-note {{because of ambiguity in conversion of 'struct C1' to 'struct E *'}} \ + // expected-note {{because of ambiguity in conversion of 'C1' to 'E *'}} \ // expected-note 4 {{built-in candidate operator}} } diff --git a/test/SemaCXX/cast-conversion.cpp b/test/SemaCXX/cast-conversion.cpp index 074e1330403d..d68e789c370f 100644 --- a/test/SemaCXX/cast-conversion.cpp +++ b/test/SemaCXX/cast-conversion.cpp @@ -13,9 +13,9 @@ struct B { }; int main () { - B(10); // expected-error {{functional-style cast from 'int' to 'struct B' is not allowed}} - (B)10; // expected-error {{C-style cast from 'int' to 'struct B' is not allowed}} - static_cast<B>(10); // expected-error {{static_cast from 'int' to 'struct B' is not allowed}} \\ + B(10); // expected-error {{functional-style cast from 'int' to 'B' is not allowed}} + (B)10; // expected-error {{C-style cast from 'int' to 'B' is not allowed}} + static_cast<B>(10); // expected-error {{static_cast from 'int' to 'B' is not allowed}} \\ // expected-warning {{expression result unused}} } diff --git a/test/SemaCXX/class-base-member-init.cpp b/test/SemaCXX/class-base-member-init.cpp index 67bc43c2e80b..1c6e79012ea5 100644 --- a/test/SemaCXX/class-base-member-init.cpp +++ b/test/SemaCXX/class-base-member-init.cpp @@ -8,7 +8,7 @@ public: struct D : S { D() : b1(0), b2(1), b1(0), S(), S() {} // expected-error {{multiple initializations given for non-static member 'b1'}} \ // expected-note {{previous initialization is here}} \ - // expected-error {{multiple initializations given for base 'class S'}} \ + // expected-error {{multiple initializations given for base 'S'}} \ // expected-note {{previous initialization is here}} int b1; diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp index b961ff2de910..4fcb0bb98dc0 100644 --- a/test/SemaCXX/conditional-expr.cpp +++ b/test/SemaCXX/conditional-expr.cpp @@ -85,7 +85,7 @@ void test() // these are ambiguous BadBase bb; BadDerived bd; - (void)(i1 ? bb : bd); // expected-error {{conditional expression is ambiguous; 'struct BadBase' can be converted to 'struct BadDerived' and vice versa}} + (void)(i1 ? bb : bd); // expected-error {{conditional expression is ambiguous; 'BadBase' can be converted to 'BadDerived' and vice versa}} (void)(i1 ? bd : bb); // expected-error {{conditional expression is ambiguous}} // curiously enough (and a defect?), these are not // for rvalues, hierarchy takes precedence over other conversions @@ -106,19 +106,19 @@ void test() i1 = (i1 ? Base() : Derived()).trick(); i1 = (i1 ? Derived() : Base()).trick(); // should fail: const lost - (void)(i1 ? Base() : constder()); // expected-error {{incompatible operand types ('struct Base' and 'struct Derived const')}} - (void)(i1 ? constder() : Base()); // expected-error {{incompatible operand types ('struct Derived const' and 'struct Base')}} + (void)(i1 ? Base() : constder()); // expected-error {{incompatible operand types ('Base' and 'Derived const')}} + (void)(i1 ? constder() : Base()); // expected-error {{incompatible operand types ('Derived const' and 'Base')}} Priv priv; Fin fin; (void)(i1 ? Base() : Priv()); // expected-error{{private base class}} (void)(i1 ? Priv() : Base()); // expected-error{{private base class}} - (void)(i1 ? Base() : Fin()); // expected-error{{ambiguous conversion from derived class 'struct Fin' to base class 'struct Base'}} - (void)(i1 ? Fin() : Base()); // expected-error{{ambiguous conversion from derived class 'struct Fin' to base class 'struct Base'}} + (void)(i1 ? Base() : Fin()); // expected-error{{ambiguous conversion from derived class 'Fin' to base class 'Base':}} + (void)(i1 ? Fin() : Base()); // expected-error{{ambiguous conversion from derived class 'Fin' to base class 'Base':}} (void)(i1 ? base : priv); // expected-error {{private base class}} (void)(i1 ? priv : base); // expected-error {{private base class}} - (void)(i1 ? base : fin); // expected-error {{ambiguous conversion from derived class 'struct Fin' to base class 'struct Base'}} - (void)(i1 ? fin : base); // expected-error {{ambiguous conversion from derived class 'struct Fin' to base class 'struct Base'}} + (void)(i1 ? base : fin); // expected-error {{ambiguous conversion from derived class 'Fin' to base class 'Base':}} + (void)(i1 ? fin : base); // expected-error {{ambiguous conversion from derived class 'Fin' to base class 'Base':}} // b2.2 (non-hierarchy) i1 = i1 ? I() : i1; @@ -128,10 +128,10 @@ void test() // "the type [it] woud have if E2 were converted to an rvalue" vfn pfn = i1 ? F() : test; pfn = i1 ? test : F(); - (void)(i1 ? A() : B()); // expected-error {{conversion from 'struct B' to 'struct A' is ambiguous}} - (void)(i1 ? B() : A()); // expected-error {{conversion from 'struct B' to 'struct A' is ambiguous}} - (void)(i1 ? 1 : Ambig()); // expected-error {{conversion from 'struct Ambig' to 'int' is ambiguous}} - (void)(i1 ? Ambig() : 1); // expected-error {{conversion from 'struct Ambig' to 'int' is ambiguous}} + (void)(i1 ? A() : B()); // expected-error {{conversion from 'B' to 'A' is ambiguous}} + (void)(i1 ? B() : A()); // expected-error {{conversion from 'B' to 'A' is ambiguous}} + (void)(i1 ? 1 : Ambig()); // expected-error {{conversion from 'Ambig' to 'int' is ambiguous}} + (void)(i1 ? Ambig() : 1); // expected-error {{conversion from 'Ambig' to 'int' is ambiguous}} // By the way, this isn't an lvalue: &(i1 ? i1 : i2); // expected-error {{address expression must be an lvalue or a function designator}} diff --git a/test/SemaCXX/const-cast.cpp b/test/SemaCXX/const-cast.cpp index 220e6faeee3c..50bd3162780b 100644 --- a/test/SemaCXX/const-cast.cpp +++ b/test/SemaCXX/const-cast.cpp @@ -59,6 +59,6 @@ short *bad_const_cast_test(char const *volatile *const volatile *var) // Function pointers. f fp2 = const_cast<f>(fp1); // expected-error {{const_cast to 'f' (aka 'int (*)(int)'), which is not a reference, pointer-to-object, or pointer-to-data-member}} void (A::*mfn)() = 0; - (void)const_cast<void (A::*)()>(mfn); // expected-error {{const_cast to 'void (struct A::*)()', which is not a reference, pointer-to-object, or pointer-to-data-member}} + (void)const_cast<void (A::*)()>(mfn); // expected-error {{const_cast to 'void (A::*)()', which is not a reference, pointer-to-object, or pointer-to-data-member}} return **var3; } diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp index 2efb7b9c2145..96dfa8ba5269 100644 --- a/test/SemaCXX/constructor-initializer.cpp +++ b/test/SemaCXX/constructor-initializer.cpp @@ -27,7 +27,7 @@ public: class E : public D, public B { public: - E() : B(), D() { } // expected-error{{base class initializer 'class B' names both a direct base class and an inherited virtual base class}} + E() : B(), D() { } // expected-error{{base class initializer 'B' names both a direct base class and an inherited virtual base class}} }; @@ -65,7 +65,7 @@ struct S : Y, virtual X { }; struct Z : S { - Z() : X(), S(), E() {} // expected-error {{type 'class E' is not a direct or virtual base of 'Z'}} + Z() : X(), S(), E() {} // expected-error {{type 'E' is not a direct or virtual base of 'Z'}} }; class U { @@ -104,13 +104,13 @@ struct M { // expected-note 2 {{candidate constructor (the implicit }; struct N : M { - N() : M(1), // expected-error {{no matching constructor for initialization of 'struct M'}} - m1(100) { } // expected-error {{no matching constructor for initialization of 'struct M'}} + N() : M(1), // expected-error {{no matching constructor for initialization of 'M'}} + m1(100) { } // expected-error {{no matching constructor for initialization of 'M'}} M m1; }; struct P : M { - P() { } // expected-error {{base class 'struct M'}} \ + P() { } // expected-error {{constructor for 'P' must explicitly initialize the base class 'M' which does not have a default constructor}} \ // expected-error {{member 'm'}} M m; // expected-note {{member is declared here}} }; diff --git a/test/SemaCXX/conversion-delete-expr.cpp b/test/SemaCXX/conversion-delete-expr.cpp index 2338778ebaac..862ae5ae02bb 100644 --- a/test/SemaCXX/conversion-delete-expr.cpp +++ b/test/SemaCXX/conversion-delete-expr.cpp @@ -11,7 +11,7 @@ struct D : B { void f (D d) { - delete d; // expected-error {{ambiguous conversion of delete expression of type 'struct D' to a pointer}} + delete d; // expected-error {{ambiguous conversion of delete expression of type 'D' to a pointer}} } // Test2 @@ -39,7 +39,7 @@ struct D2 : B2 { void f2 (D2 d) { - delete d; // expected-error {{ambiguous conversion of delete expression of type 'struct D2' to a pointer}} + delete d; // expected-error {{ambiguous conversion of delete expression of type 'D2' to a pointer}} } // Test4 @@ -56,7 +56,7 @@ struct D3 : A3, B3 { void f3 (D3 d) { - delete d; // expected-error {{mbiguous conversion of delete expression of type 'struct D3' to a pointer}} + delete d; // expected-error {{ambiguous conversion of delete expression of type 'D3' to a pointer}} } // Test5 diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp index 4fef172bd5a1..bca75c0b2fb5 100644 --- a/test/SemaCXX/conversion-function.cpp +++ b/test/SemaCXX/conversion-function.cpp @@ -49,9 +49,9 @@ class A { }; class B : public A { public: - operator A&() const; // expected-warning{{conversion function converting 'class B' to its base class 'class A' will never be used}} - operator const void() const; // expected-warning{{conversion function converting 'class B' to 'void const' will never be used}} - operator const B(); // expected-warning{{conversion function converting 'class B' to itself will never be used}} + operator A&() const; // expected-warning{{conversion function converting 'B' to its base class 'A' will never be used}} + operator const void() const; // expected-warning{{conversion function converting 'B' to 'void const' will never be used}} + operator const B(); // expected-warning{{conversion function converting 'B' to itself will never be used}} }; // This used to crash Clang. @@ -63,7 +63,7 @@ struct Flop { // expected-note{{candidate is the implicit copy constructor}} struct Flip { operator Flop() const; // expected-note{{candidate function}} }; -Flop flop = Flip(); // expected-error {{conversion from 'struct Flip' to 'struct Flop' is ambiguous}} +Flop flop = Flip(); // expected-error {{conversion from 'Flip' to 'Flop' is ambiguous}} // This tests that we don't add the second conversion declaration to the list of user conversions struct C { @@ -88,7 +88,7 @@ public: }; void f(Yb& a) { - if (a) { } // expected-error {{conversion from 'class Yb' to 'bool' is ambiguous}} + if (a) { } // expected-error {{conversion from 'Yb' to 'bool' is ambiguous}} int i = a; // OK. calls XB::operator int(); char ch = a; // OK. calls Yb::operator char(); } diff --git a/test/SemaCXX/convert-to-bool.cpp b/test/SemaCXX/convert-to-bool.cpp index 4b5002e44a01..4cd22e90c0e0 100644 --- a/test/SemaCXX/convert-to-bool.cpp +++ b/test/SemaCXX/convert-to-bool.cpp @@ -44,12 +44,12 @@ struct ExplicitConvToRef { void test_explicit_bool(ExplicitConvToBool ecb) { bool b1(ecb); // okay - bool b2 = ecb; // expected-error{{no viable conversion from 'struct ExplicitConvToBool' to 'bool'}} + bool b2 = ecb; // expected-error{{no viable conversion from 'ExplicitConvToBool' to 'bool'}} accepts_bool(ecb); // expected-error{{no matching function for call to}} } void test_explicit_conv_to_ref(ExplicitConvToRef ecr) { - int& i1 = ecr; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'struct ExplicitConvToRef'}} + int& i1 = ecr; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'ExplicitConvToRef'}} int& i2(ecr); // okay } @@ -61,7 +61,7 @@ struct C { }; void test_copy_init_conversions(C c) { - A &a = c; // expected-error{{no viable conversion from 'struct C' to 'struct A'}} + A &a = c; // expected-error{{no viable conversion from 'C' to 'A'}} B &b = b; // okay } diff --git a/test/SemaCXX/copy-assignment.cpp b/test/SemaCXX/copy-assignment.cpp index d7eb5cf1e60d..8cdb1be48763 100644 --- a/test/SemaCXX/copy-assignment.cpp +++ b/test/SemaCXX/copy-assignment.cpp @@ -94,6 +94,6 @@ void test() { int i; i = convertibleToInt; - i = a; // expected-error{{incompatible type assigning 'struct A', expected 'int'}} + i = a; // expected-error{{incompatible type assigning 'A', expected 'int'}} } diff --git a/test/SemaCXX/copy-initialization.cpp b/test/SemaCXX/copy-initialization.cpp index 2cf878a84411..3a63be0970de 100644 --- a/test/SemaCXX/copy-initialization.cpp +++ b/test/SemaCXX/copy-initialization.cpp @@ -9,7 +9,7 @@ public: class Y : public X { }; void f(Y y, int *ip, float *fp) { - X x1 = y; // expected-error{{no matching constructor for initialization of 'class X'}} + X x1 = y; // expected-error{{no matching constructor for initialization of 'X'}} X x2 = 0; X x3 = ip; X x4 = fp; // expected-error{{no viable conversion}} @@ -20,4 +20,4 @@ struct foo { }; // PR3600 -void test(const foo *P) { P->bar(); } // expected-error{{cannot initialize object parameter of type 'struct foo' with an expression of type 'struct foo const'}} +void test(const foo *P) { P->bar(); } // expected-error{{cannot initialize object parameter of type 'foo' with an expression of type 'foo const'}} diff --git a/test/SemaCXX/cstyle-cast.cpp b/test/SemaCXX/cstyle-cast.cpp index dbb1e4a18a2e..6a28f4c2c875 100644 --- a/test/SemaCXX/cstyle-cast.cpp +++ b/test/SemaCXX/cstyle-cast.cpp @@ -122,12 +122,12 @@ void t_529_5_8() // Bad code below - (void)(C1*)((A*)0); // expected-error {{cannot cast 'struct A *' to 'struct C1 *' via virtual base 'struct B'}} - (void)(C1&)(*((A*)0)); // expected-error {{cannot cast 'struct A' to 'struct C1 &' via virtual base 'struct B'}} - (void)(D*)((A*)0); // expected-error {{cannot cast 'struct A *' to 'struct D *' via virtual base 'struct B'}} - (void)(D&)(*((A*)0)); // expected-error {{cannot cast 'struct A' to 'struct D &' via virtual base 'struct B'}} - (void)(H*)((A*)0); // expected-error {{ambiguous cast from base 'struct A' to derived 'struct H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} - (void)(H&)(*((A*)0)); // expected-error {{ambiguous cast from base 'struct A' to derived 'struct H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} + (void)(C1*)((A*)0); // expected-error {{cannot cast 'A *' to 'C1 *' via virtual base 'B'}} + (void)(C1&)(*((A*)0)); // expected-error {{cannot cast 'A' to 'C1 &' via virtual base 'B'}} + (void)(D*)((A*)0); // expected-error {{cannot cast 'A *' to 'D *' via virtual base 'B'}} + (void)(D&)(*((A*)0)); // expected-error {{cannot cast 'A' to 'D &' via virtual base 'B'}} + (void)(H*)((A*)0); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} + (void)(H&)(*((A*)0)); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} // TODO: Test DR427. This requires user-defined conversions, though. } @@ -141,7 +141,7 @@ void t_529_7() // Bad code below - (void)(Enum)((int*)0); // expected-error {{C-style cast from 'int *' to 'enum Enum' is not allowed}} + (void)(Enum)((int*)0); // expected-error {{C-style cast from 'int *' to 'Enum' is not allowed}} } // Void pointer to object pointer @@ -158,8 +158,8 @@ void t_529_9() (void)(int A::*)((int B::*)0); // Bad code below - (void)(int A::*)((int H::*)0); // expected-error {{ambiguous conversion from pointer to member of derived class 'struct H'}} - (void)(int A::*)((int F::*)0); // expected-error {{conversion from pointer to member of class 'struct F'}} + (void)(int A::*)((int H::*)0); // expected-error {{ambiguous conversion from pointer to member of derived class 'H' to pointer to member of base class 'A':}} + (void)(int A::*)((int F::*)0); // expected-error {{conversion from pointer to member of class 'F' to pointer to member of class 'A' via virtual base 'B' is not allowed}} } // -------- reinterpret_cast ----------- @@ -226,6 +226,6 @@ void memptrs() void (structure::*psf)() = 0; (void)(int (structure::*)())(psf); - (void)(void (structure::*)())(psi); // expected-error {{C-style cast from 'int const struct structure::*' to 'void (struct structure::*)()' is not allowed}} - (void)(int structure::*)(psf); // expected-error {{C-style cast from 'void (struct structure::*)()' to 'int struct structure::*' is not allowed}} + (void)(void (structure::*)())(psi); // expected-error {{C-style cast from 'int const structure::*' to 'void (structure::*)()' is not allowed}} + (void)(int structure::*)(psf); // expected-error {{C-style cast from 'void (structure::*)()' to 'int structure::*' is not allowed}} } diff --git a/test/SemaCXX/dcl_init_aggr.cpp b/test/SemaCXX/dcl_init_aggr.cpp index 461c60b5bbc1..8b2866344462 100644 --- a/test/SemaCXX/dcl_init_aggr.cpp +++ b/test/SemaCXX/dcl_init_aggr.cpp @@ -13,9 +13,9 @@ struct NonAggregate { int a, b; }; -NonAggregate non_aggregate_test = { 1, 2 }; // expected-error{{non-aggregate type 'struct NonAggregate' cannot be initialized with an initializer list}} +NonAggregate non_aggregate_test = { 1, 2 }; // expected-error{{non-aggregate type 'NonAggregate' cannot be initialized with an initializer list}} -NonAggregate non_aggregate_test2[2] = { { 1, 2 }, { 3, 4 } }; // expected-error 2 {{initialization of non-aggregate type 'struct NonAggregate' with an initializer list}} +NonAggregate non_aggregate_test2[2] = { { 1, 2 }, { 3, 4 } }; // expected-error 2 {{initialization of non-aggregate type 'NonAggregate' with an initializer list}} // C++ [dcl.init.aggr]p3 @@ -51,7 +51,7 @@ struct TooFewError { // expected-error{{implicit default constructor for}} TooFewError too_few_okay = { 1, 1 }; TooFewError too_few_error = { 1 }; // expected-error{{no matching constructor}} -TooFewError too_few_okay2[2] = { 1, 1 }; // expected-note{{implicit default constructor for 'struct TooFewError' first required here}} +TooFewError too_few_okay2[2] = { 1, 1 }; // expected-note{{implicit default constructor for 'TooFewError' first required here}} TooFewError too_few_error2[2] = { 1 }; // expected-error{{no matching constructor}} NoDefaultConstructor too_few_error3[3] = { }; // expected-error {{no matching constructor}} diff --git a/test/SemaCXX/decl-init-ref.cpp b/test/SemaCXX/decl-init-ref.cpp index 2f7d8a4c77ef..7ae043925214 100644 --- a/test/SemaCXX/decl-init-ref.cpp +++ b/test/SemaCXX/decl-init-ref.cpp @@ -21,9 +21,9 @@ extern B f(); const int& ri = (void)0; // expected-error {{reference to type 'int const' could not bind to an rvalue of type 'void'}} int main() { - const A& rca = f(); // expected-error {{reference initialization of type 'struct A const &' with initializer of type 'class B' is ambiguous}} - A& ra = f(); // expected-error {{non-const lvalue reference to type 'struct A' cannot bind to a temporary of type 'class B'}} + const A& rca = f(); // expected-error {{reference initialization of type 'A const &' with initializer of type 'B' is ambiguous}} + A& ra = f(); // expected-error {{non-const lvalue reference to type 'A' cannot bind to a temporary of type 'B'}} } struct PR6139 { A (&x)[1]; }; -PR6139 x = {{A()}}; // expected-error{{non-const lvalue reference to type 'struct A [1]' cannot bind to a temporary of type 'struct A'}} +PR6139 x = {{A()}}; // expected-error{{non-const lvalue reference to type 'A [1]' cannot bind to a temporary of type 'A'}} diff --git a/test/SemaCXX/decltype-overloaded-functions.cpp b/test/SemaCXX/decltype-overloaded-functions.cpp index 906e868a4282..0aa49b0cec90 100644 --- a/test/SemaCXX/decltype-overloaded-functions.cpp +++ b/test/SemaCXX/decltype-overloaded-functions.cpp @@ -9,4 +9,4 @@ template<typename T> struct S { }; struct K { void f(); void f(int); }; -S<K> b; // expected-note{{in instantiation of template class 'struct S<struct K>' requested here}} +S<K> b; // expected-note{{in instantiation of template class 'S<K>' requested here}} diff --git a/test/SemaCXX/default-assignment-operator.cpp b/test/SemaCXX/default-assignment-operator.cpp index 9c99ad594458..baae03cf1347 100644 --- a/test/SemaCXX/default-assignment-operator.cpp +++ b/test/SemaCXX/default-assignment-operator.cpp @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -class Base { // expected-error {{cannot define the implicit default assignment operator for 'class Base'}} +class Base { // expected-error {{cannot define the implicit default assignment operator for 'Base', because non-static reference member 'ref' can't use default assignment operator}} int &ref; // expected-note {{declared at}} }; -class X : Base { // // expected-error {{cannot define the implicit default assignment operator for 'class X'}} +class X : Base { // // expected-error {{cannot define the implicit default assignment operator for 'X', because non-static const member 'cint' can't use default assignment operator}} public: X(); const int cint; // expected-note {{declared at}} @@ -70,7 +70,7 @@ void i() { // Test5 -class E1 { // expected-error{{cannot define the implicit default assignment operator for 'class E1', because non-static const member 'a' can't use default assignment operator}} +class E1 { // expected-error{{cannot define the implicit default assignment operator for 'E1', because non-static const member 'a' can't use default assignment operator}} public: const int a; // expected-note{{declared at}} E1() : a(0) {} diff --git a/test/SemaCXX/default-constructor-initializers.cpp b/test/SemaCXX/default-constructor-initializers.cpp index 4269991adecf..b40b133a5541 100644 --- a/test/SemaCXX/default-constructor-initializers.cpp +++ b/test/SemaCXX/default-constructor-initializers.cpp @@ -4,12 +4,11 @@ struct X1 { // has no implicit default constructor X1(int); }; -struct X2 : X1 { // expected-note {{'struct X2' declared here}} \ - // expected-note {{'struct X2' declared here}} +struct X2 : X1 { // expected-note 2 {{'X2' declared here}} X2(int); }; -struct X3 : public X2 { // expected-error {{must explicitly initialize the base class 'struct X2'}} +struct X3 : public X2 { // expected-error {{implicit default constructor for 'X3' must explicitly initialize the base class 'X2' which does not have a default constructor}} }; X3 x3; // expected-note {{first required here}} diff --git a/test/SemaCXX/default2.cpp b/test/SemaCXX/default2.cpp index e674260680fc..a0999c0c4c62 100644 --- a/test/SemaCXX/default2.cpp +++ b/test/SemaCXX/default2.cpp @@ -91,12 +91,12 @@ public: } void test_Z(const Z& z) { - Z z2(z); // expected-error{{no matching constructor for initialization of 'class Z'}} + Z z2(z); // expected-error{{no matching constructor for initialization of 'Z'}} } }; void test_Z(const Z& z) { - Z z2(z); // expected-error{{no matching constructor for initialization of 'class Z'}} + Z z2(z); // expected-error{{no matching constructor for initialization of 'Z'}} } struct ZZ { diff --git a/test/SemaCXX/deleted-function.cpp b/test/SemaCXX/deleted-function.cpp index d9df1bf5b05a..b3e129600421 100644 --- a/test/SemaCXX/deleted-function.cpp +++ b/test/SemaCXX/deleted-function.cpp @@ -29,7 +29,7 @@ void test() { ov(1); ov(1.0); // expected-error {{call to deleted function 'ov'}} - WithDel dd; // expected-error {{call to deleted constructor of 'struct WithDel'}} + WithDel dd; // expected-error {{call to deleted constructor of 'WithDel'}} WithDel *d = 0; d->fn(); // expected-error {{attempt to use a deleted function}} int i = *d; // expected-error {{invokes a deleted function}} diff --git a/test/SemaCXX/derived-to-base-ambig.cpp b/test/SemaCXX/derived-to-base-ambig.cpp index cfcad7989aa2..9216e5b03798 100644 --- a/test/SemaCXX/derived-to-base-ambig.cpp +++ b/test/SemaCXX/derived-to-base-ambig.cpp @@ -6,7 +6,7 @@ class D : public B, public C { }; void f(D* d) { A* a; - a = d; // expected-error{{ambiguous conversion from derived class 'class D' to base class 'class A'}} expected-error{{incompatible type assigning 'class D *', expected 'class A *'}} + a = d; // expected-error{{ambiguous conversion from derived class 'D' to base class 'A':}} expected-error{{incompatible type assigning 'D *', expected 'A *'}} } class Object2 { }; @@ -20,7 +20,7 @@ class F2 : public E2, public A2 { }; void g(E2* e2, F2* f2) { Object2* o2; o2 = e2; - o2 = f2; // expected-error{{ambiguous conversion from derived class 'class F2' to base class 'class Object2'}} expected-error{{incompatible type assigning 'class F2 *', expected 'class Object2 *'}} + o2 = f2; // expected-error{{ambiguous conversion from derived class 'F2' to base class 'Object2':}} expected-error{{incompatible type assigning 'F2 *', expected 'Object2 *'}} } // Test that ambiguous/inaccessibility checking does not trigger too diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp index ab3c809e00a8..7010d2e0d092 100644 --- a/test/SemaCXX/destructor.cpp +++ b/test/SemaCXX/destructor.cpp @@ -32,7 +32,7 @@ struct E; typedef E E_typedef; struct E { - ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'struct E') of the class name}} + ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'E') of the class name}} }; struct F { diff --git a/test/SemaCXX/direct-initializer.cpp b/test/SemaCXX/direct-initializer.cpp index 6601a3dd0d92..d30642b5c3ec 100644 --- a/test/SemaCXX/direct-initializer.cpp +++ b/test/SemaCXX/direct-initializer.cpp @@ -28,11 +28,11 @@ public: void g() { X x1(5); X x2(1.0, 3, 4.2); - X x3(1.0, 1.0); // expected-error{{no matching constructor for initialization of 'class X'}} + X x3(1.0, 1.0); // expected-error{{no matching constructor for initialization of 'X'}} Y y(1.0); X x4(3.14, y); - Z z; // expected-error{{no matching constructor for initialization of 'class Z'}} + Z z; // expected-error{{no matching constructor for initialization of 'Z'}} } struct Base { @@ -44,7 +44,7 @@ struct Derived : Base { }; void foo(const Derived cd, Derived d) { - int *pi = cd; // expected-error {{no viable conversion from 'struct Derived const' to 'int *'}} + int *pi = cd; // expected-error {{no viable conversion from 'Derived const' to 'int *'}} int *ppi = d; } diff --git a/test/SemaCXX/dynamic-cast.cpp b/test/SemaCXX/dynamic-cast.cpp index 53d0b9d0189c..b73e8c57b9f3 100644 --- a/test/SemaCXX/dynamic-cast.cpp +++ b/test/SemaCXX/dynamic-cast.cpp @@ -8,7 +8,7 @@ struct D : private A {}; struct E : A {}; struct F : B, E {}; -struct Incomplete; // expected-note 2 {{forward declaration of 'struct Incomplete'}} +struct Incomplete; // expected-note 2 {{forward declaration of 'Incomplete'}} struct Poly { @@ -22,7 +22,7 @@ struct PolyDerived : Poly void basic_bad() { // ptr -> nonptr - (void)dynamic_cast<A>((A*)0); // expected-error {{'struct A' is not a reference or pointer}} + (void)dynamic_cast<A>((A*)0); // expected-error {{'A' is not a reference or pointer}} // nonptr -> ptr (void)dynamic_cast<A*>(0); // expected-error {{'int' is not a pointer}} // ptr -> noncls @@ -34,9 +34,9 @@ void basic_bad() // noncls -> ref (void)dynamic_cast<A&>(*((int*)0)); // expected-error {{'int' is not a class}} // ptr -> incomplete - (void)dynamic_cast<Incomplete*>((A*)0); // expected-error {{'struct Incomplete' is an incomplete type}} + (void)dynamic_cast<Incomplete*>((A*)0); // expected-error {{'Incomplete' is an incomplete type}} // incomplete -> ptr - (void)dynamic_cast<A*>((Incomplete*)0); // expected-error {{'struct Incomplete' is an incomplete type}} + (void)dynamic_cast<A*>((Incomplete*)0); // expected-error {{'Incomplete' is an incomplete type}} } void same() @@ -57,8 +57,8 @@ void up() //(void)dynamic_cast<A&>(*((D*)0)); // Ambiguous - (void)dynamic_cast<A*>((F*)0); // expected-error {{ambiguous conversion from derived class 'struct F' to base class 'struct A':\n struct F -> struct B -> struct A\n struct F -> struct E -> struct A}} - (void)dynamic_cast<A&>(*((F*)0)); // expected-error {{ambiguous conversion from derived class 'struct F' to base class 'struct A':\n struct F -> struct B -> struct A\n struct F -> struct E -> struct A}} + (void)dynamic_cast<A*>((F*)0); // expected-error {{ambiguous conversion from derived class 'F' to base class 'A':\n struct F -> struct B -> struct A\n struct F -> struct E -> struct A}} + (void)dynamic_cast<A&>(*((F*)0)); // expected-error {{ambiguous conversion from derived class 'F' to base class 'A':\n struct F -> struct B -> struct A\n struct F -> struct E -> struct A}} } void poly() @@ -69,6 +69,6 @@ void poly() (void)dynamic_cast<A&>(*((PolyDerived*)0)); // Not polymorphic source - (void)dynamic_cast<Poly*>((A*)0); // expected-error {{'struct A' is not polymorphic}} - (void)dynamic_cast<PolyDerived&>(*((A*)0)); // expected-error {{'struct A' is not polymorphic}} + (void)dynamic_cast<Poly*>((A*)0); // expected-error {{'A' is not polymorphic}} + (void)dynamic_cast<PolyDerived&>(*((A*)0)); // expected-error {{'A' is not polymorphic}} } diff --git a/test/SemaCXX/elaborated-type-specifier.cpp b/test/SemaCXX/elaborated-type-specifier.cpp index 8d2d67f705cd..3cd3a1bc2241 100644 --- a/test/SemaCXX/elaborated-type-specifier.cpp +++ b/test/SemaCXX/elaborated-type-specifier.cpp @@ -27,7 +27,7 @@ namespace NS { void test_X_elab(NS::X x) { struct S4 *s4 = 0; - x.test_elab2(s4); // expected-error{{cannot initialize a parameter of type 'struct NS::S4 *' with an lvalue of type 'struct S4 *'}} + x.test_elab2(s4); // expected-error{{cannot initialize a parameter of type 'NS::S4 *' with an lvalue of type 'struct S4 *'}} } namespace NS { diff --git a/test/SemaCXX/exception-spec.cpp b/test/SemaCXX/exception-spec.cpp index 291b359dfdc4..782cf838569f 100644 --- a/test/SemaCXX/exception-spec.cpp +++ b/test/SemaCXX/exception-spec.cpp @@ -29,10 +29,10 @@ struct Incomplete; // expected-note 3 {{forward declaration}} // Exception spec must not have incomplete types, or pointers to them, except // void. void ic1() throw(void); // expected-error {{incomplete type 'void' is not allowed in exception specification}} -void ic2() throw(Incomplete); // expected-error {{incomplete type 'struct Incomplete' is not allowed in exception specification}} +void ic2() throw(Incomplete); // expected-error {{incomplete type 'Incomplete' is not allowed in exception specification}} void ic3() throw(void*); -void ic4() throw(Incomplete*); // expected-error {{pointer to incomplete type 'struct Incomplete' is not allowed in exception specification}} -void ic5() throw(Incomplete&); // expected-error {{reference to incomplete type 'struct Incomplete' is not allowed in exception specification}} +void ic4() throw(Incomplete*); // expected-error {{pointer to incomplete type 'Incomplete' is not allowed in exception specification}} +void ic5() throw(Incomplete&); // expected-error {{reference to incomplete type 'Incomplete' is not allowed in exception specification}} // Redeclarations typedef int INT; diff --git a/test/SemaCXX/exceptions.cpp b/test/SemaCXX/exceptions.cpp index 924b48aad26f..2ed4bfe88562 100644 --- a/test/SemaCXX/exceptions.cpp +++ b/test/SemaCXX/exceptions.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -struct A; // expected-note 4 {{forward declaration of 'struct A'}} +struct A; // expected-note 4 {{forward declaration of 'A'}} struct Abstract { virtual void f() = 0; }; // expected-note {{pure virtual function 'f'}} @@ -11,9 +11,9 @@ void trys() { int i; // expected-error {{redefinition of 'i'}} } catch(float i) { } catch(void v) { // expected-error {{cannot catch incomplete type 'void'}} - } catch(A a) { // expected-error {{cannot catch incomplete type 'struct A'}} - } catch(A *a) { // expected-error {{cannot catch pointer to incomplete type 'struct A'}} - } catch(A &a) { // expected-error {{cannot catch reference to incomplete type 'struct A'}} + } catch(A a) { // expected-error {{cannot catch incomplete type 'A'}} + } catch(A *a) { // expected-warning {{ISO C++ forbids catching a pointer to incomplete type 'A'}} + } catch(A &a) { // expected-warning {{ISO C++ forbids catching a reference to incomplete type 'A'}} } catch(Abstract) { // expected-error {{variable type 'Abstract' is an abstract class}} } catch(...) { int j = i; // expected-error {{use of undeclared identifier 'i'}} @@ -29,7 +29,7 @@ void throws() { throw; throw 0; throw throw; // expected-error {{cannot throw object of incomplete type 'void'}} - throw (A*)0; // expected-error {{cannot throw pointer to object of incomplete type 'struct A'}} + throw (A*)0; // expected-error {{cannot throw pointer to object of incomplete type 'A'}} } void jumps() { diff --git a/test/SemaCXX/functional-cast.cpp b/test/SemaCXX/functional-cast.cpp index 0bef0cd6be4c..4e0486c79ac2 100644 --- a/test/SemaCXX/functional-cast.cpp +++ b/test/SemaCXX/functional-cast.cpp @@ -175,17 +175,17 @@ void t_529_5_8() // Bad code below typedef C1 *C1p; - (void)C1p((A*)0); // expected-error {{cannot cast 'struct A *' to 'C1p' (aka 'struct C1 *') via virtual base 'struct B'}} + (void)C1p((A*)0); // expected-error {{cannot cast 'A *' to 'C1p' (aka 'C1 *') via virtual base 'B'}} typedef C1 &C1r; - (void)C1r(*((A*)0)); // expected-error {{cannot cast 'struct A' to 'C1r' (aka 'struct C1 &') via virtual base 'struct B'}} + (void)C1r(*((A*)0)); // expected-error {{cannot cast 'A' to 'C1r' (aka 'C1 &') via virtual base 'B'}} typedef D *Dp; - (void)Dp((A*)0); // expected-error {{cannot cast 'struct A *' to 'Dp' (aka 'struct D *') via virtual base 'struct B'}} + (void)Dp((A*)0); // expected-error {{cannot cast 'A *' to 'Dp' (aka 'D *') via virtual base 'B'}} typedef D &Dr; - (void)Dr(*((A*)0)); // expected-error {{cannot cast 'struct A' to 'Dr' (aka 'struct D &') via virtual base 'struct B'}} + (void)Dr(*((A*)0)); // expected-error {{cannot cast 'A' to 'Dr' (aka 'D &') via virtual base 'B'}} typedef H *Hp; - (void)Hp((A*)0); // expected-error {{ambiguous cast from base 'struct A' to derived 'struct H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} + (void)Hp((A*)0); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} typedef H &Hr; - (void)Hr(*((A*)0)); // expected-error {{ambiguous cast from base 'struct A' to derived 'struct H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} + (void)Hr(*((A*)0)); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} // TODO: Test DR427. This requires user-defined conversions, though. } @@ -199,7 +199,7 @@ void t_529_7() // Bad code below - (void)Enum((int*)0); // expected-error {{functional-style cast from 'int *' to 'enum Enum' is not allowed}} + (void)Enum((int*)0); // expected-error {{functional-style cast from 'int *' to 'Enum' is not allowed}} } // Void pointer to object pointer @@ -219,8 +219,8 @@ void t_529_9() (void)Amp((int B::*)0); // Bad code below - (void)Amp((int H::*)0); // expected-error {{ambiguous conversion from pointer to member of derived class 'struct H'}} - (void)Amp((int F::*)0); // expected-error {{conversion from pointer to member of class 'struct F'}} + (void)Amp((int H::*)0); // expected-error {{ambiguous conversion from pointer to member of derived class 'H' to pointer to member of base class 'A':}} + (void)Amp((int F::*)0); // expected-error {{conversion from pointer to member of class 'F' to pointer to member of class 'A' via virtual base 'B' is not allowed}} } // -------- reinterpret_cast ----------- @@ -304,8 +304,8 @@ void memptrs() (void)structureimfp(psf); typedef void (structure::*structurevmfp)(); - (void)structurevmfp(psi); // expected-error {{functional-style cast from 'int const struct structure::*' to 'structurevmfp' (aka 'void (struct structure::*)()') is not allowed}} - (void)structureimp(psf); // expected-error {{functional-style cast from 'void (struct structure::*)()' to 'structureimp' (aka 'int struct structure::*') is not allowed}} + (void)structurevmfp(psi); // expected-error {{functional-style cast from 'int const structure::*' to 'structurevmfp' (aka 'void (structure::*)()') is not allowed}} + (void)structureimp(psf); // expected-error {{functional-style cast from 'void (structure::*)()' to 'structureimp' (aka 'int structure::*') is not allowed}} } // ---------------- misc ------------------ diff --git a/test/SemaCXX/illegal-member-initialization.cpp b/test/SemaCXX/illegal-member-initialization.cpp index be5f91d51ac8..3fb0b93fc4f6 100644 --- a/test/SemaCXX/illegal-member-initialization.cpp +++ b/test/SemaCXX/illegal-member-initialization.cpp @@ -10,10 +10,10 @@ struct B { }; struct X { - X() { } // expected-error {{constructor for 'struct X' must explicitly initialize the reference member 'value'}} \ - // expected-error {{constructor for 'struct X' must explicitly initialize the const member 'cvalue'}} \ - // expected-error {{constructor for 'struct X' must explicitly initialize the reference member 'b'}} \ - // expected-error {{constructor for 'struct X' must explicitly initialize the const member 'cb'}} + X() { } // expected-error {{constructor for 'X' must explicitly initialize the reference member 'value'}} \ + // expected-error {{constructor for 'X' must explicitly initialize the const member 'cvalue'}} \ + // expected-error {{constructor for 'X' must explicitly initialize the reference member 'b'}} \ + // expected-error {{constructor for 'X' must explicitly initialize the const member 'cb'}} int &value; // expected-note{{declared at}} const int cvalue; // expected-note{{declared at}} B& b; // expected-note{{declared at}} diff --git a/test/SemaCXX/implicit-virtual-member-functions.cpp b/test/SemaCXX/implicit-virtual-member-functions.cpp index 1bb5adbb861f..cb245011a873 100644 --- a/test/SemaCXX/implicit-virtual-member-functions.cpp +++ b/test/SemaCXX/implicit-virtual-member-functions.cpp @@ -9,7 +9,7 @@ struct B : A { // expected-error {{no suitable member 'operator delete' in 'B'}} void operator delete (void *, int); // expected-note {{'operator delete' declared here}} }; -void B::f() { // expected-note {{implicit default destructor for 'struct B' first required here}} +void B::f() { // expected-note {{implicit default destructor for 'B' first required here}} } struct C : A { // expected-error {{no suitable member 'operator delete' in 'C'}} @@ -17,11 +17,11 @@ struct C : A { // expected-error {{no suitable member 'operator delete' in 'C'}} void operator delete(void *, int); // expected-note {{'operator delete' declared here}} }; -C::C() { } // expected-note {{implicit default destructor for 'struct C' first required here}} +C::C() { } // expected-note {{implicit default destructor for 'C' first required here}} struct D : A { // expected-error {{no suitable member 'operator delete' in 'D'}} void operator delete(void *, int); // expected-note {{'operator delete' declared here}} -}; // expected-note {{implicit default destructor for 'struct D' first required here}} +}; // expected-note {{implicit default destructor for 'D' first required here}} void f() { new D; diff --git a/test/SemaCXX/incomplete-call.cpp b/test/SemaCXX/incomplete-call.cpp index 5bdaf829e64e..d627c33d8352 100644 --- a/test/SemaCXX/incomplete-call.cpp +++ b/test/SemaCXX/incomplete-call.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -struct A; // expected-note 14 {{forward declaration of 'struct A'}} +struct A; // expected-note 14 {{forward declaration of 'A'}} A f(); // expected-note {{note: 'f' declared here}} @@ -15,29 +15,29 @@ struct B { }; void g() { - f(); // expected-error {{calling 'f' with incomplete return type 'struct A'}} + f(); // expected-error {{calling 'f' with incomplete return type 'A'}} typedef A (*Func)(); Func fp; - fp(); // expected-error {{calling function with incomplete return type 'struct A'}} - ((Func)0)(); // expected-error {{calling function with incomplete return type 'struct A'}} + fp(); // expected-error {{calling function with incomplete return type 'A'}} + ((Func)0)(); // expected-error {{calling function with incomplete return type 'A'}} B b; - b.f(); // expected-error {{calling 'f' with incomplete return type 'struct A'}} + b.f(); // expected-error {{calling 'f' with incomplete return type 'A'}} - b.operator()(); // expected-error {{calling 'operator()' with incomplete return type 'struct A'}} - b.operator A(); // expected-error {{calling 'operator A' with incomplete return type 'struct A'}} - b.operator!(); // expected-error {{calling 'operator!' with incomplete return type 'struct A'}} + b.operator()(); // expected-error {{calling 'operator()' with incomplete return type 'A'}} + b.operator A(); // expected-error {{calling 'operator A' with incomplete return type 'A'}} + b.operator!(); // expected-error {{calling 'operator!' with incomplete return type 'A'}} - !b; // expected-error {{calling 'operator!' with incomplete return type 'struct A'}} - b(); // expected-error {{calling 'operator()' with incomplete return type 'struct A'}} - b++; // expected-error {{calling 'operator++' with incomplete return type 'struct A'}} - b[0]; // expected-error {{calling 'operator[]' with incomplete return type 'struct A'}} - b + 1; // expected-error {{calling 'operator+' with incomplete return type 'struct A'}} - b->f(); // expected-error {{calling 'operator->' with incomplete return type 'struct A'}} + !b; // expected-error {{calling 'operator!' with incomplete return type 'A'}} + b(); // expected-error {{calling 'operator()' with incomplete return type 'A'}} + b++; // expected-error {{calling 'operator++' with incomplete return type 'A'}} + b[0]; // expected-error {{calling 'operator[]' with incomplete return type 'A'}} + b + 1; // expected-error {{calling 'operator+' with incomplete return type 'A'}} + b->f(); // expected-error {{calling 'operator->' with incomplete return type 'A'}} A (B::*mfp)() = 0; - (b.*mfp)(); // expected-error {{calling function with incomplete return type 'struct A'}} + (b.*mfp)(); // expected-error {{calling function with incomplete return type 'A'}} } diff --git a/test/SemaCXX/inherit.cpp b/test/SemaCXX/inherit.cpp index aabed2bff9e7..a926c812514c 100644 --- a/test/SemaCXX/inherit.cpp +++ b/test/SemaCXX/inherit.cpp @@ -10,7 +10,7 @@ class B3 : virtual virtual A { }; // expected-error{{duplicate 'virtual' in base class C : public B1, private B2 { }; -class D; // expected-note {{forward declaration of 'class D'}} +class D; // expected-note {{forward declaration of 'D'}} class E : public D { }; // expected-error{{base class has incomplete type}} @@ -28,5 +28,5 @@ typedef G G_copy; typedef G G_copy_2; typedef G_copy G_copy_3; -class H : G_copy, A, G_copy_2, // expected-error{{base class 'G_copy' (aka 'class G') specified more than once as a direct base class}} - public G_copy_3 { }; // expected-error{{base class 'G_copy' (aka 'class G') specified more than once as a direct base class}} +class H : G_copy, A, G_copy_2, // expected-error{{base class 'G_copy' (aka 'G') specified more than once as a direct base class}} + public G_copy_3 { }; // expected-error{{base class 'G_copy' (aka 'G') specified more than once as a direct base class}} diff --git a/test/SemaCXX/member-name-lookup.cpp b/test/SemaCXX/member-name-lookup.cpp index 94296e1132f1..01491693deac 100644 --- a/test/SemaCXX/member-name-lookup.cpp +++ b/test/SemaCXX/member-name-lookup.cpp @@ -35,11 +35,11 @@ struct D : B, C { }; void test_lookup(D d) { - d.a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'struct A'}} + d.a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'A':}} (void)d.b; // okay d.c; // expected-error{{member 'c' found in multiple base classes of different types}} d.d; // expected-error{{member 'd' found in multiple base classes of different types}} - d.f(0); // expected-error{{non-static member 'f' found in multiple base-class subobjects of type 'struct A'}} + d.f(0); // expected-error{{non-static member 'f' found in multiple base-class subobjects of type 'A':}} d.static_f(0); // okay D::E e = D::enumerator; // okay @@ -51,11 +51,11 @@ void test_lookup(D d) { } void D::test_lookup() { - a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'struct A'}} + a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'A':}} (void)b; // okay c; // expected-error{{member 'c' found in multiple base classes of different types}} d; // expected-error{{member 'd' found in multiple base classes of different types}} - f(0); // expected-error{{non-static member 'f' found in multiple base-class subobjects of type 'struct A'}} + f(0); // expected-error{{non-static member 'f' found in multiple base-class subobjects of type 'A':}} static_f(0); // okay E e = enumerator; // okay @@ -105,7 +105,7 @@ void test_virtual_lookup(D2 d2, G g) { D2::E3 e3; // expected-error{{member 'E3' found in multiple base classes of different types}} - g.a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'struct A'}} + g.a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'A':}} g.static_f(0); // okay } @@ -126,7 +126,7 @@ void D2::test_virtual_lookup() { } void G::test_virtual_lookup() { - a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'struct A'}} + a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'A':}} static_f(0); // okay } diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp index d6050cd7337a..92ae92d710ce 100644 --- a/test/SemaCXX/member-pointer.cpp +++ b/test/SemaCXX/member-pointer.cpp @@ -34,11 +34,11 @@ void f() { pdid = pdi2; // Fail conversion due to ambiguity and virtuality. - int F::*pdif = pdi1; // expected-error {{ambiguous conversion from pointer to member of base class 'struct A' to pointer to member of derived class 'struct F'}} - int G::*pdig = pdi1; // expected-error {{conversion from pointer to member of class 'struct A' to pointer to member of class 'struct G' via virtual base 'struct D' is not allowed}} + int F::*pdif = pdi1; // expected-error {{ambiguous conversion from pointer to member of base class 'A' to pointer to member of derived class 'F':}} + int G::*pdig = pdi1; // expected-error {{conversion from pointer to member of class 'A' to pointer to member of class 'G' via virtual base 'D' is not allowed}} // Conversion to member of base. - pdi1 = pdid; // expected-error {{incompatible type assigning 'int struct D::*', expected 'int struct A::*'}} + pdi1 = pdid; // expected-error {{incompatible type assigning 'int D::*', expected 'int A::*'}} // Comparisons int (A::*pf2)(int, int); @@ -104,8 +104,8 @@ void h() { (hm.*pf)(); (phm->*pf)(); - (void)(hm->*pi); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct HasMembers'}} - (void)(phm.*pi); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'struct HasMembers *'}} + (void)(hm->*pi); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'HasMembers'}} + (void)(phm.*pi); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'HasMembers *'}} (void)(i.*pi); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'int'}} int *ptr; (void)(ptr->*pi); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'int *'}} @@ -115,8 +115,8 @@ void h() { (void)(d.*pai); (void)(pd->*pai); F f, *ptrf = &f; - (void)(f.*pai); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'struct F'}} - (void)(ptrf->*pai); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct F *'}} + (void)(f.*pai); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'F'}} + (void)(ptrf->*pai); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'F *'}} (void)(hm.*i); // expected-error {{pointer-to-member}} (void)(phm->*i); // expected-error {{pointer-to-member}} diff --git a/test/SemaCXX/missing-members.cpp b/test/SemaCXX/missing-members.cpp index 9ec17f7b9933..529ba1023dcd 100644 --- a/test/SemaCXX/missing-members.cpp +++ b/test/SemaCXX/missing-members.cpp @@ -9,7 +9,7 @@ namespace A { void f() { A::B::i; // expected-error {{no member named 'i' in namespace 'A::B'}} - A::B::C::i; // expected-error {{no member named 'i' in 'class A::B::C'}} + A::B::C::i; // expected-error {{no member named 'i' in 'A::B::C'}} ::i; // expected-error {{no member named 'i' in the global namespace}} } @@ -19,18 +19,18 @@ namespace B { void g() { A::B::D::E; // expected-error {{no member named 'D' in namespace 'A::B'}} - B::B::C::D; // expected-error {{no member named 'C' in 'class B::B'}} + B::B::C::D; // expected-error {{no member named 'C' in 'B::B'}} ::C::D; // expected-error {{no member named 'C' in the global namespace}} } int A::B::i = 10; // expected-error {{no member named 'i' in namespace 'A::B'}} -int A::B::C::i = 10; // expected-error {{no member named 'i' in 'class A::B::C'}} -int A::B::S::i = 10; // expected-error {{no member named 'i' in 'struct A::B::S'}} -int A::B::U::i = 10; // expected-error {{no member named 'i' in 'union A::B::U'}} +int A::B::C::i = 10; // expected-error {{no member named 'i' in 'A::B::C'}} +int A::B::S::i = 10; // expected-error {{no member named 'i' in 'A::B::S'}} +int A::B::U::i = 10; // expected-error {{no member named 'i' in 'A::B::U'}} using A::B::D; // expected-error {{no member named 'D' in namespace 'A::B'}} struct S : A::B::C { - using A::B::C::f; // expected-error {{no member named 'f' in 'class A::B::C'}} + using A::B::C::f; // expected-error {{no member named 'f' in 'A::B::C'}} }; diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp index 247e91b2eb39..8657c0dca0ae 100644 --- a/test/SemaCXX/nested-name-spec.cpp +++ b/test/SemaCXX/nested-name-spec.cpp @@ -36,9 +36,9 @@ class C2 { int x; }; -void C2::m() const { } // expected-error{{out-of-line definition of 'm' does not match any declaration in 'class C2'}} +void C2::m() const { } // expected-error{{out-of-line definition of 'm' does not match any declaration in 'C2'}} -void C2::f(int) { } // expected-error{{out-of-line definition of 'f' does not match any declaration in 'class C2'}} +void C2::f(int) { } // expected-error{{out-of-line definition of 'f' does not match any declaration in 'C2'}} void C2::m() { x = 0; @@ -125,7 +125,7 @@ class Operators { operator bool(); }; -Operators Operators::operator+(const Operators&) { // expected-error{{out-of-line definition of 'operator+' does not match any declaration in 'class Operators'}} +Operators Operators::operator+(const Operators&) { // expected-error{{out-of-line definition of 'operator+' does not match any declaration in 'Operators'}} Operators ops; return ops; } @@ -149,7 +149,7 @@ void A::g(const int&) { } // expected-error{{out-of-line definition of 'g' does struct Struct { }; -void Struct::f() { } // expected-error{{out-of-line definition of 'f' does not match any declaration in 'struct Struct'}} +void Struct::f() { } // expected-error{{out-of-line definition of 'f' does not match any declaration in 'Struct'}} void global_func(int); void global_func2(int); @@ -164,8 +164,8 @@ void ::global_func2(int) { } // expected-error{{definition or redeclaration of ' void N::f() { } // okay -struct Y; // expected-note{{forward declaration of 'struct Y'}} -Y::foo y; // expected-error{{incomplete type 'struct Y' named in nested name specifier}} \ +struct Y; // expected-note{{forward declaration of 'Y'}} +Y::foo y; // expected-error{{incomplete type 'Y' named in nested name specifier}} \ // expected-error{{no type named 'foo' in}} X::X() : a(5) { } // expected-error{{use of undeclared identifier 'X'}} \ @@ -227,6 +227,6 @@ namespace test3 { // FIXME: this should really only trigger once class A; // expected-note 2 {{forward declaration}} void foo(const char *path) { - A::execute(path); // expected-error 2 {{incomplete type 'class test3::A' named in nested name specifier}} + A::execute(path); // expected-error 2 {{incomplete type 'test3::A' named in nested name specifier}} } } diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp index 68323d8d0756..ae77e704f501 100644 --- a/test/SemaCXX/new-delete.cpp +++ b/test/SemaCXX/new-delete.cpp @@ -8,7 +8,7 @@ struct S // expected-note {{candidate}} S(double, int); // expected-note 2 {{candidate}} S(float, int); // expected-note 2 {{candidate}} }; -struct T; // expected-note{{forward declaration of 'struct T'}} +struct T; // expected-note{{forward declaration of 'T'}} struct U { // A special new, to verify that the global version isn't used. @@ -60,15 +60,15 @@ void bad_news(int *ip) (void)new int[1][i]; // expected-error {{only the first dimension}} (void)new (int[1][i]); // expected-error {{only the first dimension}} (void)new (int[i]); // expected-error {{when type is in parentheses}} - (void)new int(*(S*)0); // expected-error {{no viable conversion from 'struct S' to 'int'}} + (void)new int(*(S*)0); // expected-error {{no viable conversion from 'S' to 'int'}} (void)new int(1, 2); // expected-error {{excess elements in scalar initializer}} (void)new S(1); // expected-error {{no matching constructor}} - (void)new S(1, 1); // expected-error {{call to constructor of 'struct S' is ambiguous}} + (void)new S(1, 1); // expected-error {{call to constructor of 'S' is ambiguous}} (void)new const int; // expected-error {{default initialization of an object of const type 'int const'}} (void)new float*(ip); // expected-error {{cannot initialize a new value of type 'float *' with an lvalue of type 'int *'}} // Undefined, but clang should reject it directly. (void)new int[-1]; // expected-error {{array size is negative}} - (void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumerated type, not 'struct S'}} + (void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumerated type, not 'S'}} (void)::S::new int; // expected-error {{expected unqualified-id}} (void)new (0, 0) int; // expected-error {{no matching function for call to 'operator new'}} (void)new (0L) int; // expected-error {{call to 'operator new' is ambiguous}} @@ -114,7 +114,7 @@ struct X2 { void test_delete_conv(X0 x0, X1 x1, X2 x2) { delete x0; // expected-error{{cannot delete}} delete x1; - delete x2; // expected-error{{ambiguous conversion of delete expression of type 'struct X2' to a pointer}} + delete x2; // expected-error{{ambiguous conversion of delete expression of type 'X2' to a pointer}} } // PR4782 @@ -199,7 +199,7 @@ struct X11 : X10 { // expected-error {{no suitable member 'operator delete' in ' }; void f() { - X11 x11; // expected-note {{implicit default destructor for 'struct X11' first required here}} + X11 x11; // expected-note {{implicit default destructor for 'X11' first required here}} } struct X12 { diff --git a/test/SemaCXX/offsetof.cpp b/test/SemaCXX/offsetof.cpp index f3dc52df4977..3283270847fd 100644 --- a/test/SemaCXX/offsetof.cpp +++ b/test/SemaCXX/offsetof.cpp @@ -10,7 +10,7 @@ struct P { }; void f() { - int i = __builtin_offsetof(P, fieldThatPointsToANonPODType.m); // expected-warning{{offset of on non-POD type 'struct P'}} + int i = __builtin_offsetof(P, fieldThatPointsToANonPODType.m); // expected-warning{{offset of on non-POD type 'P'}} } struct Base { int x; }; diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index 77e0908ef46d..c286028c29af 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -386,3 +386,23 @@ namespace DerivedToBase { float &fr = f0(C()); } } + +namespace PR6483 { + struct X0 { + operator const unsigned int & () const; + }; + + struct X1 { + operator unsigned int & () const; + }; + + void f0(const bool &); + void f1(bool &); // expected-note 2{{not viable}} + + void g(X0 x0, X1 x1) { + f0(x0); + f1(x0); // expected-error{{no matching function for call}} + f0(x1); + f1(x1); // expected-error{{no matching function for call}} + } +} diff --git a/test/SemaCXX/overload-member-call.cpp b/test/SemaCXX/overload-member-call.cpp index 77d9965ab796..8016b116812f 100644 --- a/test/SemaCXX/overload-member-call.cpp +++ b/test/SemaCXX/overload-member-call.cpp @@ -78,11 +78,11 @@ namespace test1 { void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}} void foo(int n, const char *s, int t, int u = 0); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}} - void bar(double d); //expected-note {{candidate function not viable: 'this' argument has type 'class test1::A const', but method is not marked const}} - void bar(int i); //expected-note {{candidate function not viable: 'this' argument has type 'class test1::A const', but method is not marked const}} + void bar(double d); //expected-note {{candidate function not viable: 'this' argument has type 'test1::A const', but method is not marked const}} + void bar(int i); //expected-note {{candidate function not viable: 'this' argument has type 'test1::A const', but method is not marked const}} - void baz(A &d); // expected-note {{candidate function not viable: 1st argument ('class test1::A const') would lose const qualifier}} - void baz(int i); // expected-note {{candidate function not viable: no known conversion from 'class test1::A const' to 'int' for 1st argument}} + void baz(A &d); // expected-note {{candidate function not viable: 1st argument ('test1::A const') would lose const qualifier}} + void baz(int i); // expected-note {{candidate function not viable: no known conversion from 'test1::A const' to 'int' for 1st argument}} }; void test() { diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index e07afe202031..89f181469fdf 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -38,7 +38,7 @@ bool operator==(A&, Z&); // expected-note 2{{candidate function}} void h(A a, const A ac, Z z) { make_A() == z; a == z; // expected-error{{use of overloaded operator '==' is ambiguous; candidates are:}} - ac == z; // expected-error{{invalid operands to binary expression ('struct A const' and 'struct Z')}} + ac == z; // expected-error{{invalid operands to binary expression ('A const' and 'Z')}} } struct B { @@ -172,7 +172,7 @@ void test_callable(Callable c, Callable2 c2, const Callable2& c2c, int &ir = c(1); float &fr = c(1, 3.14159, 17, 42); - c(); // expected-error{{no matching function for call to object of type 'struct Callable'; candidates are:}} + c(); // expected-error{{no matching function for call to object of type 'Callable'}} double &dr = c(1.0f); @@ -200,12 +200,12 @@ struct ConvertToFuncDerived : ConvertToFunc { }; void test_funcptr_call(ConvertToFunc ctf, ConvertToFuncDerived ctfd) { int &i1 = ctf(1.0f, 2.0); float &f1 = ctf((short int)1, 1.0f); - ctf((long int)17, 2.0); // expected-error{{error: call to object of type 'struct ConvertToFunc' is ambiguous; candidates are:}} + ctf((long int)17, 2.0); // expected-error{{call to object of type 'ConvertToFunc' is ambiguous}} ctf(); int &i2 = ctfd(1.0f, 2.0); float &f2 = ctfd((short int)1, 1.0f); - ctfd((long int)17, 2.0); // expected-error{{error: call to object of type 'struct ConvertToFuncDerived' is ambiguous; candidates are:}} + ctfd((long int)17, 2.0); // expected-error{{call to object of type 'ConvertToFuncDerived' is ambiguous}} ctfd(); } diff --git a/test/SemaCXX/qual-id-test.cpp b/test/SemaCXX/qual-id-test.cpp index 00dc662d0670..54d41b81cab6 100644 --- a/test/SemaCXX/qual-id-test.cpp +++ b/test/SemaCXX/qual-id-test.cpp @@ -48,7 +48,7 @@ namespace C a.A::sub::x(); a.A::B::base::x(); - a.bad::x(); // expected-error{{type 'struct bad' is not a direct or virtual base of ''A::sub''}} + a.bad::x(); // expected-error{{type 'bad' is not a direct or virtual base of ''A::sub''}} a->foo(); a->member::foo(); @@ -69,7 +69,7 @@ namespace C a->A::sub::x(); a->A::B::base::x(); - a->bad::x(); // expected-error{{type 'struct bad' is not a direct or virtual base of ''A::sub''}} + a->bad::x(); // expected-error{{type 'bad' is not a direct or virtual base of ''A::sub''}} (*a)->foo(); (*a)->member::foo(); diff --git a/test/SemaCXX/qualified-id-lookup.cpp b/test/SemaCXX/qualified-id-lookup.cpp index a187d4908cd4..abde62efceae 100644 --- a/test/SemaCXX/qualified-id-lookup.cpp +++ b/test/SemaCXX/qualified-id-lookup.cpp @@ -96,12 +96,12 @@ void test_a() { a::a::a::i = 4; } -struct Undef { // expected-note{{definition of 'struct Undef' is not complete until the closing '}'}} +struct Undef { // expected-note{{definition of 'Undef' is not complete until the closing '}'}} typedef int type; Undef::type member; - static int size = sizeof(Undef); // expected-error{{invalid application of 'sizeof' to an incomplete type 'struct Undef'}} + static int size = sizeof(Undef); // expected-error{{invalid application of 'sizeof' to an incomplete type 'Undef'}} int f(); }; diff --git a/test/SemaCXX/qualified-names-diag.cpp b/test/SemaCXX/qualified-names-diag.cpp index 86c10888b8a2..c8b5746a39a6 100644 --- a/test/SemaCXX/qualified-names-diag.cpp +++ b/test/SemaCXX/qualified-names-diag.cpp @@ -16,7 +16,7 @@ namespace foo { namespace bar { typedef int y; - struct incomplete; // expected-note{{forward declaration of 'struct bar::incomplete'}} + struct incomplete; // expected-note{{forward declaration of 'bar::incomplete'}} } void test() { foo::wibble::x a; diff --git a/test/SemaCXX/ref-init-ambiguous.cpp b/test/SemaCXX/ref-init-ambiguous.cpp index 976879ecd0ae..8844162052d9 100644 --- a/test/SemaCXX/ref-init-ambiguous.cpp +++ b/test/SemaCXX/ref-init-ambiguous.cpp @@ -14,15 +14,15 @@ struct C : B, A { }; void test(C c) { - const E2 &e2 = c; // expected-error {{reference initialization of type 'enum E2 const &' with initializer of type 'struct C' is ambiguous}} + const E2 &e2 = c; // expected-error {{reference initialization of type 'E2 const &' with initializer of type 'C' is ambiguous}} } void foo(const E2 &); const E2 & re(C c) { - foo(c); // expected-error {{reference initialization of type 'enum E2 const &' with initializer of type 'struct C' is ambiguous}} + foo(c); // expected-error {{reference initialization of type 'E2 const &' with initializer of type 'C' is ambiguous}} - return c; // expected-error {{reference initialization of type 'enum E2 const &' with initializer of type 'struct C' is ambiguous}} + return c; // expected-error {{reference initialization of type 'E2 const &' with initializer of type 'C' is ambiguous}} } diff --git a/test/SemaCXX/references.cpp b/test/SemaCXX/references.cpp index df8337bec82c..f1f4ab9f9541 100644 --- a/test/SemaCXX/references.cpp +++ b/test/SemaCXX/references.cpp @@ -73,7 +73,7 @@ class Test6 { struct C : B, A { }; void test7(C& c) { - A& a1 = c; // expected-error {{ambiguous conversion from derived class 'struct C' to base class 'struct A':}} + A& a1 = c; // expected-error {{ambiguous conversion from derived class 'C' to base class 'A':}} } // C++ [dcl.ref]p1, C++ [dcl.ref]p4 diff --git a/test/SemaCXX/reinterpret-cast.cpp b/test/SemaCXX/reinterpret-cast.cpp index f7ab80e67fd0..45d41e84601a 100644 --- a/test/SemaCXX/reinterpret-cast.cpp +++ b/test/SemaCXX/reinterpret-cast.cpp @@ -13,7 +13,7 @@ void self_conversion() int i = 0; (void)reinterpret_cast<int>(i); // expected-error {{reinterpret_cast from 'int' to 'int' is not allowed}} structure s; - (void)reinterpret_cast<structure>(s); // expected-error {{reinterpret_cast from 'struct structure' to 'struct structure' is not allowed}} + (void)reinterpret_cast<structure>(s); // expected-error {{reinterpret_cast from 'structure' to 'structure' is not allowed}} int *pi = 0; (void)reinterpret_cast<int*>(pi); } @@ -77,18 +77,18 @@ void memptrs() { const int structure::*psi = 0; (void)reinterpret_cast<const float structure::*>(psi); - (void)reinterpret_cast<int structure::*>(psi); // expected-error {{reinterpret_cast from 'int const struct structure::*' to 'int struct structure::*' casts away constness}} + (void)reinterpret_cast<int structure::*>(psi); // expected-error {{reinterpret_cast from 'int const structure::*' to 'int structure::*' casts away constness}} void (structure::*psf)() = 0; (void)reinterpret_cast<int (structure::*)()>(psf); - (void)reinterpret_cast<void (structure::*)()>(psi); // expected-error {{reinterpret_cast from 'int const struct structure::*' to 'void (struct structure::*)()' is not allowed}} - (void)reinterpret_cast<int structure::*>(psf); // expected-error {{reinterpret_cast from 'void (struct structure::*)()' to 'int struct structure::*' is not allowed}} + (void)reinterpret_cast<void (structure::*)()>(psi); // expected-error {{reinterpret_cast from 'int const structure::*' to 'void (structure::*)()' is not allowed}} + (void)reinterpret_cast<int structure::*>(psf); // expected-error {{reinterpret_cast from 'void (structure::*)()' to 'int structure::*' is not allowed}} // Cannot cast from integers to member pointers, not even the null pointer // literal. - (void)reinterpret_cast<void (structure::*)()>(0); // expected-error {{reinterpret_cast from 'int' to 'void (struct structure::*)()' is not allowed}} - (void)reinterpret_cast<int structure::*>(0); // expected-error {{reinterpret_cast from 'int' to 'int struct structure::*' is not allowed}} + (void)reinterpret_cast<void (structure::*)()>(0); // expected-error {{reinterpret_cast from 'int' to 'void (structure::*)()' is not allowed}} + (void)reinterpret_cast<int structure::*>(0); // expected-error {{reinterpret_cast from 'int' to 'int structure::*' is not allowed}} } // PR5545 diff --git a/test/SemaCXX/rval-references.cpp b/test/SemaCXX/rval-references.cpp index 2a7fb25c62a9..d5b465f0786e 100644 --- a/test/SemaCXX/rval-references.cpp +++ b/test/SemaCXX/rval-references.cpp @@ -44,7 +44,7 @@ void f() { conv_to_not_int_rvalue cnir; not_int &&ni4 = cnir; // expected-error {{rvalue reference cannot bind to lvalue}} - not_int &ni5 = cnir; // expected-error{{non-const lvalue reference to type 'struct not_int' cannot bind to a value of unrelated type 'struct conv_to_not_int_rvalue'}} + not_int &ni5 = cnir; // expected-error{{non-const lvalue reference to type 'not_int' cannot bind to a value of unrelated type 'conv_to_not_int_rvalue'}} not_int &&ni6 = conv_to_not_int_rvalue(); @@ -83,5 +83,5 @@ MoveOnly returningNonEligible() { else if (0) // Copy from reference can't be elided return r; // expected-error {{call to deleted constructor}} else // Construction from different type can't be elided - return i; // expected-error {{no viable conversion from 'int' to 'struct MoveOnly'}} + return i; // expected-error {{no viable conversion from 'int' to 'MoveOnly'}} } diff --git a/test/SemaCXX/statements.cpp b/test/SemaCXX/statements.cpp index 852086ed9a94..0e27f4645af4 100644 --- a/test/SemaCXX/statements.cpp +++ b/test/SemaCXX/statements.cpp @@ -15,3 +15,8 @@ void test2() { later: ; } + +namespace PR6536 { + struct A {}; + void a() { goto out; A x; out: return; } +} diff --git a/test/SemaCXX/static-assert.cpp b/test/SemaCXX/static-assert.cpp index 62208cd2aeeb..516243ec70e1 100644 --- a/test/SemaCXX/static-assert.cpp +++ b/test/SemaCXX/static-assert.cpp @@ -18,13 +18,13 @@ template<int N> struct T { static_assert(N == 2, "N is not 2!"); // expected-error {{static_assert failed "N is not 2!"}} }; -T<1> t1; // expected-note {{in instantiation of template class 'struct T<1>' requested here}} +T<1> t1; // expected-note {{in instantiation of template class 'T<1>' requested here}} T<2> t2; template<typename T> struct S { static_assert(sizeof(T) > sizeof(char), "Type not big enough!"); // expected-error {{static_assert failed "Type not big enough!"}} }; -S<char> s1; // expected-note {{in instantiation of template class 'struct S<char>' requested here}} +S<char> s1; // expected-note {{in instantiation of template class 'S<char>' requested here}} S<int> s2; diff --git a/test/SemaCXX/static-cast-complete-type.cpp b/test/SemaCXX/static-cast-complete-type.cpp index 11bf22dfe899..6d76f813f8d9 100644 --- a/test/SemaCXX/static-cast-complete-type.cpp +++ b/test/SemaCXX/static-cast-complete-type.cpp @@ -3,11 +3,11 @@ template<typename T> struct S { S(int); }; -struct T; // expected-note{{forward declaration of 'struct T'}} +struct T; // expected-note{{forward declaration of 'T'}} void f() { S<int> s0 = static_cast<S<int> >(0); S<void*> s1 = static_cast<S<void*> >(00); - (void)static_cast<T>(10); // expected-error{{'struct T' is an incomplete type}} + (void)static_cast<T>(10); // expected-error{{'T' is an incomplete type}} } diff --git a/test/SemaCXX/static-cast.cpp b/test/SemaCXX/static-cast.cpp index 4818b041ad08..2630278d9f6b 100644 --- a/test/SemaCXX/static-cast.cpp +++ b/test/SemaCXX/static-cast.cpp @@ -56,10 +56,10 @@ void t_529_2() // Bad code below (void)static_cast<void*>((const int*)0); // expected-error {{static_cast from 'int const *' to 'void *' is not allowed}} - (void)static_cast<A*>((E*)0); // expected-error {{private base class 'struct A'}} + (void)static_cast<A*>((E*)0); // expected-error {{cannot cast 'E' to its private base class 'A'}} (void)static_cast<A*>((H*)0); // expected-error {{ambiguous conversion}} (void)static_cast<int>((int*)0); // expected-error {{static_cast from 'int *' to 'int' is not allowed}} - (void)static_cast<A**>((B**)0); // expected-error {{static_cast from 'struct B **' to 'struct A **' is not allowed}} + (void)static_cast<A**>((B**)0); // expected-error {{static_cast from 'B **' to 'A **' is not allowed}} (void)static_cast<char&>(i); // expected-error {{non-const lvalue reference to type 'char' cannot be initialized with a value of type 'int'}} } @@ -80,18 +80,18 @@ void t_529_5_8() // Bad code below - (void)static_cast<C1*>((A*)0); // expected-error {{cannot cast 'struct A *' to 'struct C1 *' via virtual base 'struct B'}} - (void)static_cast<C1&>(*((A*)0)); // expected-error {{cannot cast 'struct A' to 'struct C1 &' via virtual base 'struct B'}} - (void)static_cast<D*>((A*)0); // expected-error {{cannot cast 'struct A *' to 'struct D *' via virtual base 'struct B'}} - (void)static_cast<D&>(*((A*)0)); // expected-error {{cannot cast 'struct A' to 'struct D &' via virtual base 'struct B'}} - (void)static_cast<B*>((const A*)0); // expected-error {{static_cast from 'struct A const *' to 'struct B *' casts away constness}} - (void)static_cast<B&>(*((const A*)0)); // expected-error {{static_cast from 'struct A const' to 'struct B &' casts away constness}} - (void)static_cast<E*>((A*)0); // expected-error {{cannot cast private base class 'struct A' to 'struct E'}} - (void)static_cast<E&>(*((A*)0)); // expected-error {{cannot cast private base class 'struct A' to 'struct E'}} - (void)static_cast<H*>((A*)0); // expected-error {{ambiguous cast from base 'struct A' to derived 'struct H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} - (void)static_cast<H&>(*((A*)0)); // expected-error {{ambiguous cast from base 'struct A' to derived 'struct H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} - (void)static_cast<E*>((B*)0); // expected-error {{static_cast from 'struct B *' to 'struct E *' is not allowed}} - (void)static_cast<E&>(*((B*)0)); // expected-error {{non-const lvalue reference to type 'struct E' cannot be initialized with a value of type 'struct B'}} + (void)static_cast<C1*>((A*)0); // expected-error {{cannot cast 'A *' to 'C1 *' via virtual base 'B'}} + (void)static_cast<C1&>(*((A*)0)); // expected-error {{cannot cast 'A' to 'C1 &' via virtual base 'B'}} + (void)static_cast<D*>((A*)0); // expected-error {{cannot cast 'A *' to 'D *' via virtual base 'B'}} + (void)static_cast<D&>(*((A*)0)); // expected-error {{cannot cast 'A' to 'D &' via virtual base 'B'}} + (void)static_cast<B*>((const A*)0); // expected-error {{static_cast from 'A const *' to 'B *' casts away constness}} + (void)static_cast<B&>(*((const A*)0)); // expected-error {{static_cast from 'A const' to 'B &' casts away constness}} + (void)static_cast<E*>((A*)0); // expected-error {{cannot cast private base class 'A' to 'E'}} + (void)static_cast<E&>(*((A*)0)); // expected-error {{cannot cast private base class 'A' to 'E'}} + (void)static_cast<H*>((A*)0); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} + (void)static_cast<H&>(*((A*)0)); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} + (void)static_cast<E*>((B*)0); // expected-error {{static_cast from 'B *' to 'E *' is not allowed}} + (void)static_cast<E&>(*((B*)0)); // expected-error {{non-const lvalue reference to type 'E' cannot be initialized with a value of type 'B'}} // TODO: Test inaccessible base in context where it's accessible, i.e. // member function and friend. @@ -108,7 +108,7 @@ void t_529_7() // Bad code below - (void)static_cast<Enum>((int*)0); // expected-error {{static_cast from 'int *' to 'enum Enum' is not allowed}} + (void)static_cast<Enum>((int*)0); // expected-error {{static_cast from 'int *' to 'Enum' is not allowed}} } // Void pointer to object pointer @@ -129,8 +129,8 @@ void t_529_9() (void)static_cast<int A::*>((int B::*)0); // Bad code below - (void)static_cast<int A::*>((int H::*)0); // expected-error {{ambiguous conversion from pointer to member of derived class 'struct H'}} - (void)static_cast<int A::*>((int F::*)0); // expected-error {{conversion from pointer to member of class 'struct F'}} + (void)static_cast<int A::*>((int H::*)0); // expected-error {{ambiguous conversion from pointer to member of derived class 'H' to pointer to member of base class 'A':}} + (void)static_cast<int A::*>((int F::*)0); // expected-error {{conversion from pointer to member of class 'F' to pointer to member of class 'A' via virtual base 'B' is not allowed}} } // PR 5261 - static_cast should instantiate template if possible @@ -181,3 +181,17 @@ struct X4 { // PR5897 - accept static_cast from const void* to const int (*)[1]. void PR5897() { (void)static_cast<const int(*)[1]>((const void*)0); } + +namespace PR6072 { + struct A { }; + struct B : A { void f(int); void f(); }; + struct C : B { }; + struct D { }; + + void f() { + (void)static_cast<void (A::*)()>(&B::f); + (void)static_cast<void (B::*)()>(&B::f); + (void)static_cast<void (C::*)()>(&B::f); + (void)static_cast<void (D::*)()>(&B::f); // expected-error{{static_cast from '<overloaded function type>' to 'void (PR6072::D::*)()' is not allowed}} + } +} diff --git a/test/SemaCXX/type-traits-incomplete.cpp b/test/SemaCXX/type-traits-incomplete.cpp index 0ef6917c5911..f95982157900 100644 --- a/test/SemaCXX/type-traits-incomplete.cpp +++ b/test/SemaCXX/type-traits-incomplete.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -struct S; // expected-note{{forward declaration of 'struct S'}} +struct S; // expected-note{{forward declaration of 'S'}} void f() { - __is_pod(S); // expected-error{{incomplete type 'struct S' used in type trait expression}} + __is_pod(S); // expected-error{{incomplete type 'S' used in type trait expression}} } diff --git a/test/SemaCXX/typedef-redecl.cpp b/test/SemaCXX/typedef-redecl.cpp index 0d8dc8487bf7..c382539e05f1 100644 --- a/test/SemaCXX/typedef-redecl.cpp +++ b/test/SemaCXX/typedef-redecl.cpp @@ -11,10 +11,10 @@ struct X { }; struct Y; // expected-note{{previous definition is here}} -typedef int Y; // expected-error{{typedef redefinition with different types ('int' vs 'struct Y')}} +typedef int Y; // expected-error{{typedef redefinition with different types ('int' vs 'Y')}} typedef int Y2; // expected-note{{previous definition is here}} -struct Y2; // expected-error{{definition of type 'struct Y2' conflicts with typedef of the same name}} +struct Y2; // expected-error{{definition of type 'Y2' conflicts with typedef of the same name}} void f(); // expected-note{{previous definition is here}} typedef int f; // expected-error{{redefinition of 'f' as different kind of symbol}} diff --git a/test/SemaCXX/typeid.cpp b/test/SemaCXX/typeid.cpp index 7960cac78310..0e78ff46a65c 100644 --- a/test/SemaCXX/typeid.cpp +++ b/test/SemaCXX/typeid.cpp @@ -18,7 +18,7 @@ void g() struct X; // expected-note 3{{forward declaration}} void g1(X &x) { - (void)typeid(X); // expected-error{{'typeid' of incomplete type 'struct X'}} - (void)typeid(X&); // expected-error{{'typeid' of incomplete type 'struct X'}} - (void)typeid(x); // expected-error{{'typeid' of incomplete type 'struct X'}} + (void)typeid(X); // expected-error{{'typeid' of incomplete type 'X'}} + (void)typeid(X&); // expected-error{{'typeid' of incomplete type 'X'}} + (void)typeid(x); // expected-error{{'typeid' of incomplete type 'X'}} } diff --git a/test/SemaCXX/unknown-type-name.cpp b/test/SemaCXX/unknown-type-name.cpp index 084a81104d55..5f8d8caae698 100644 --- a/test/SemaCXX/unknown-type-name.cpp +++ b/test/SemaCXX/unknown-type-name.cpp @@ -9,10 +9,10 @@ namespace N { } using namespace N; -foo::bar x; // expected-error{{no type named 'bar' in 'struct N::Wibble'}} +foo::bar x; // expected-error{{no type named 'bar' in 'N::Wibble'}} void f() { - foo::bar = 4; // expected-error{{no member named 'bar' in 'struct N::Wibble'}} + foo::bar = 4; // expected-error{{no member named 'bar' in 'N::Wibble'}} } template<typename T> diff --git a/test/SemaCXX/using-decl-templates.cpp b/test/SemaCXX/using-decl-templates.cpp index 8f2876ce4b32..5148ed5bcc71 100644 --- a/test/SemaCXX/using-decl-templates.cpp +++ b/test/SemaCXX/using-decl-templates.cpp @@ -13,7 +13,7 @@ template<typename T> struct B : A<T> { using A<double>::f; // expected-error{{using declaration refers into 'A<double>::', which is not a base class of 'B<int>'}} }; -B<int> a; // expected-note{{in instantiation of template class 'struct B<int>' requested here}} +B<int> a; // expected-note{{in instantiation of template class 'B<int>' requested here}} template<typename T> struct C : A<T> { using A<T>::f; diff --git a/test/SemaCXX/value-initialization.cpp b/test/SemaCXX/value-initialization.cpp index d6a86c4c8cb5..16a7a1d0c9b9 100644 --- a/test/SemaCXX/value-initialization.cpp +++ b/test/SemaCXX/value-initialization.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x -struct A { // expected-error {{implicit default constructor for 'struct A' must explicitly initialize the const member 'i'}} +struct A { // expected-error {{implicit default constructor for 'A' must explicitly initialize the const member 'i'}} const int i; // expected-note {{declared at}} virtual void f() { } }; diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp index 5f95446d41f2..d31f1f7196aa 100644 --- a/test/SemaCXX/vararg-non-pod.cpp +++ b/test/SemaCXX/vararg-non-pod.cpp @@ -15,7 +15,7 @@ void t1() { C c(10); - g(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic function; call will abort at runtime}} + g(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}} g(10, version); } @@ -23,10 +23,10 @@ void t2() { C c(10); - c.g(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}} + c.g(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}} c.g(10, version); - C::h(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic function; call will abort at runtime}} + C::h(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}} C::h(10, version); } @@ -36,7 +36,7 @@ void t3() { C c(10); - block(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic block; call will abort at runtime}} + block(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}} block(10, version); } @@ -51,7 +51,7 @@ void t4() D d; - d(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}} + d(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}} d(10, version); } @@ -63,8 +63,8 @@ void t5() { C c(10); - E e(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic constructor; call will abort at runtime}} - (void)E(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic constructor; call will abort at runtime}} + E e(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}} + (void)E(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}} } // PR5761: unevaluated operands and the non-POD warning @@ -85,6 +85,6 @@ Base &get_base(...); int eat_base(...); void test_typeid(Base &base) { - (void)typeid(get_base(base)); // expected-warning{{cannot pass object of non-POD type 'struct Base' through variadic function; call will abort at runtime}} + (void)typeid(get_base(base)); // expected-warning{{cannot pass object of non-POD type 'Base' through variadic function; call will abort at runtime}} (void)typeid(eat_base(base)); // okay } diff --git a/test/SemaCXX/vector-casts.cpp b/test/SemaCXX/vector-casts.cpp index 6ee619ef0647..4bb580843973 100644 --- a/test/SemaCXX/vector-casts.cpp +++ b/test/SemaCXX/vector-casts.cpp @@ -22,10 +22,10 @@ void f() { (void)reinterpret_cast<__v2si>(ll); (void)(__v2si)(ll); - (void)reinterpret_cast<S>(v2si); // expected-error {{reinterpret_cast from '__v2si' to 'struct S' is not allowed}} - (void)(S)v2si; // expected-error {{C-style cast from '__v2si' to 'struct S' is not allowed}} - (void)reinterpret_cast<__v2si>(s); // expected-error {{reinterpret_cast from 'struct S' to '__v2si' is not allowed}} - (void)(__v2si)s; // expected-error {{C-style cast from 'struct S' to '__v2si' is not allowed}} + (void)reinterpret_cast<S>(v2si); // expected-error {{reinterpret_cast from '__v2si' to 'S' is not allowed}} + (void)(S)v2si; // expected-error {{C-style cast from '__v2si' to 'S' is not allowed}} + (void)reinterpret_cast<__v2si>(s); // expected-error {{reinterpret_cast from 'S' to '__v2si' is not allowed}} + (void)(__v2si)s; // expected-error {{C-style cast from 'S' to '__v2si' is not allowed}} (void)reinterpret_cast<unsigned char>(v2si); // expected-error {{reinterpret_cast from vector '__v2si' to scalar 'unsigned char' of different size}} (void)(unsigned char)v2si; // expected-error {{C-style cast from vector '__v2si' to scalar 'unsigned char' of different size}} diff --git a/test/SemaCXX/virtual-member-functions-key-function.cpp b/test/SemaCXX/virtual-member-functions-key-function.cpp index 2e21fb7365e9..97164d93affc 100644 --- a/test/SemaCXX/virtual-member-functions-key-function.cpp +++ b/test/SemaCXX/virtual-member-functions-key-function.cpp @@ -6,11 +6,11 @@ struct A { struct B : A { // expected-error {{no suitable member 'operator delete' in 'B'}} B() { } void operator delete(void *, int); // expected-note {{'operator delete' declared here}} -}; // expected-note {{implicit default destructor for 'struct B' first required here}} +}; // expected-note {{implicit default destructor for 'B' first required here}} struct C : A { // expected-error {{no suitable member 'operator delete' in 'C'}} void operator delete(void *, int); // expected-note {{'operator delete' declared here}} -}; // expected-note {{implicit default destructor for 'struct C' first required here}} +}; // expected-note {{implicit default destructor for 'C' first required here}} void f() { (void)new B; diff --git a/test/SemaCXX/virtual-override.cpp b/test/SemaCXX/virtual-override.cpp index 09cbfadf9b37..688713582657 100644 --- a/test/SemaCXX/virtual-override.cpp +++ b/test/SemaCXX/virtual-override.cpp @@ -21,7 +21,7 @@ class A { }; class B : A { - virtual b* f(); // expected-error{{return type of virtual function 'f' is not covariant with the return type of the function it overrides ('struct T2::b *' is not derived from 'struct T2::a *')}} + virtual b* f(); // expected-error{{return type of virtual function 'f' is not covariant with the return type of the function it overrides ('T2::b *' is not derived from 'T2::a *')}} }; } @@ -36,7 +36,7 @@ class A { }; class B : A { - virtual b* f(); // expected-error{{invalid covariant return for virtual function: 'struct T3::a' is a private base class of 'struct T3::b'}} + virtual b* f(); // expected-error{{invalid covariant return for virtual function: 'T3::a' is a private base class of 'T3::b'}} }; } @@ -52,7 +52,7 @@ class A { }; class B : A { - virtual b* f(); // expected-error{{return type of virtual function 'f' is not covariant with the return type of the function it overrides (ambiguous conversion from derived class 'struct T4::b' to base class 'struct T4::a':\n\ + virtual b* f(); // expected-error{{return type of virtual function 'f' is not covariant with the return type of the function it overrides (ambiguous conversion from derived class 'T4::b' to base class 'T4::a':\n\ struct T4::b -> struct T4::a\n\ struct T4::b -> struct T4::a1 -> struct T4::a)}} }; @@ -70,7 +70,7 @@ class A { class B : A { virtual a* const f(); - virtual a* g(); // expected-error{{return type of virtual function 'g' is not covariant with the return type of the function it overrides ('struct T5::a *' has different qualifiers than 'struct T5::a *const')}} + virtual a* g(); // expected-error{{return type of virtual function 'g' is not covariant with the return type of the function it overrides ('T5::a *' has different qualifiers than 'T5::a *const')}} }; } @@ -86,7 +86,7 @@ class A { class B : A { virtual a* f(); - virtual const a* g(); // expected-error{{return type of virtual function 'g' is not covariant with the return type of the function it overrides (class type 'struct T6::a const *' is more qualified than class type 'struct T6::a *'}} + virtual const a* g(); // expected-error{{return type of virtual function 'g' is not covariant with the return type of the function it overrides (class type 'T6::a const *' is more qualified than class type 'T6::a *'}} }; } @@ -106,14 +106,14 @@ namespace T7 { namespace T8 { struct a { }; - struct b; // expected-note {{forward declaration of 'struct T8::b'}} + struct b; // expected-note {{forward declaration of 'T8::b'}} class A { virtual a *f(); }; class B : A { - b* f(); // expected-error {{return type of virtual function 'f' is not covariant with the return type of the function it overrides ('struct T8::b' is incomplete)}} + b* f(); // expected-error {{return type of virtual function 'f' is not covariant with the return type of the function it overrides ('T8::b' is incomplete)}} }; } @@ -129,7 +129,7 @@ namespace T9 { }; class B : A { - virtual b<int> *f(); // expected-note {{in instantiation of template class 'struct T9::b<int>' requested here}} + virtual b<int> *f(); // expected-note {{in instantiation of template class 'T9::b<int>' requested here}} }; } @@ -230,7 +230,7 @@ namespace type_dependent_covariance { }; template <int N, int M> struct X1 : X<N> { virtual TD<M>* f1(); // expected-error{{return type of virtual function 'f1' is not covariant with the return type of the function it overrides ('TD<1> *'}} - virtual D* f2(); // expected-error{{return type of virtual function 'f2' is not covariant with the return type of the function it overrides ('struct type_dependent_covariance::D *' is not derived from 'TB<1> *')}} + virtual D* f2(); // expected-error{{return type of virtual function 'f2' is not covariant with the return type of the function it overrides ('type_dependent_covariance::D *' is not derived from 'TB<1> *')}} }; X1<0, 0> good; @@ -260,7 +260,7 @@ namespace T11 { }; struct D : C { - virtual B&& f(); // expected-error {{virtual function 'f' has a different return type ('struct T11::B &&') than the function it overrides (which has return type 'struct T11::A &')}} + virtual B&& f(); // expected-error {{virtual function 'f' has a different return type ('T11::B &&') than the function it overrides (which has return type 'T11::A &')}} }; }; @@ -273,6 +273,6 @@ namespace T12 { }; struct D : C { - virtual B& f(); // expected-error {{virtual function 'f' has a different return type ('struct T12::B &') than the function it overrides (which has return type 'struct T12::A &&')}} + virtual B& f(); // expected-error {{virtual function 'f' has a different return type ('T12::B &') than the function it overrides (which has return type 'T12::A &&')}} }; }; diff --git a/test/SemaCXX/warn-reorder-ctor-initialization.cpp b/test/SemaCXX/warn-reorder-ctor-initialization.cpp index 35b32b26a066..2634202172a2 100644 --- a/test/SemaCXX/warn-reorder-ctor-initialization.cpp +++ b/test/SemaCXX/warn-reorder-ctor-initialization.cpp @@ -9,9 +9,9 @@ public: complex() : s2(1), // expected-warning {{member 's2' will be initialized after}} s1(1) , // expected-note {{field s1}} s3(3), // expected-warning {{member 's3' will be initialized after}} - BB1(), // expected-note {{base 'struct BB1'}} \ - // expected-warning {{base class 'struct BB1' will be initialized after}} - BB() {} // expected-note {{base 'struct BB'}} + BB1(), // expected-note {{base 'BB1'}} \ + // expected-warning {{base class 'BB1' will be initialized after}} + BB() {} // expected-note {{base 'BB'}} int s1; int s2; int s3; @@ -44,14 +44,14 @@ struct C : public A, public B, private virtual V { struct D : public A, public B { - D() : A(), V() { } // expected-warning {{base class 'struct A' will be initialized after}} \ - // expected-note {{base 'struct V'}} + D() : A(), V() { } // expected-warning {{base class 'A' will be initialized after}} \ + // expected-note {{base 'V'}} }; struct E : public A, public B, private virtual V { - E() : A(), V() { } // expected-warning {{base class 'struct A' will be initialized after}} \ - // expected-note {{base 'struct V'}} + E() : A(), V() { } // expected-warning {{base class 'A' will be initialized after}} \ + // expected-note {{base 'V'}} }; @@ -64,13 +64,13 @@ struct B1 { }; struct F : public A1, public B1, private virtual V { - F() : A1(), V() { } // expected-warning {{base class 'struct A1' will be initialized after}} \ - // expected-note {{base 'struct V'}} + F() : A1(), V() { } // expected-warning {{base class 'A1' will be initialized after}} \ + // expected-note {{base 'V'}} }; struct X : public virtual A, virtual V, public virtual B { - X(): A(), V(), B() {} // expected-warning {{base class 'struct A' will be initialized after}} \ - // expected-note {{base 'struct V'}} + X(): A(), V(), B() {} // expected-warning {{base class 'A' will be initialized after}} \ + // expected-note {{base 'V'}} }; class Anon { diff --git a/test/SemaObjC/blocks.m b/test/SemaObjC/blocks.m index 36292309732b..ddac7d1759ec 100644 --- a/test/SemaObjC/blocks.m +++ b/test/SemaObjC/blocks.m @@ -55,3 +55,15 @@ int foo9() { } } + +// rdar 7725203 +@class NSString; + +extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); + +void foo10() { + void(^myBlock)(void) = ^{ + }; + NSLog(@"%@", myBlock); +} + diff --git a/test/SemaObjC/exprs.m b/test/SemaObjC/exprs.m index 33b144461f2b..3370bda0517a 100644 --- a/test/SemaObjC/exprs.m +++ b/test/SemaObjC/exprs.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify -Wno-unreachable-code +// RUN: %clang_cc1 %s -fsyntax-only -fblocks -verify -Wno-unreachable-code // rdar://6597252 Class test1(Class X) { @@ -19,3 +19,6 @@ void test2() { if (@encode(int) == "foo") { } // expected-warning {{result of comparison against @encode is unspecified}} } + +#define MAX(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; }) +void (^foo)(int, int) = ^(int x, int y) { int z = MAX(x, y); }; diff --git a/test/SemaObjCXX/cstyle-cast.mm b/test/SemaObjCXX/cstyle-cast.mm index 4a211e319704..c4b176c975ee 100644 --- a/test/SemaObjCXX/cstyle-cast.mm +++ b/test/SemaObjCXX/cstyle-cast.mm @@ -18,7 +18,7 @@ void test1(X x) { I<P> *ip = (I<P>*)cft; - (id)x; // expected-error {{C-style cast from 'struct X' to 'id' is not allowed}} + (id)x; // expected-error {{C-style cast from 'X' to 'id' is not allowed}} id *pid = (id*)ccct; diff --git a/test/SemaObjCXX/vararg-non-pod.mm b/test/SemaObjCXX/vararg-non-pod.mm index 6ced8e426bc5..7e5c4c6c97a0 100644 --- a/test/SemaObjCXX/vararg-non-pod.mm +++ b/test/SemaObjCXX/vararg-non-pod.mm @@ -17,7 +17,7 @@ void t1(D *d) { C c(10); - [d g:10, c]; // expected-warning{{cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}} + [d g:10, c]; // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}} [d g:10, version]; } diff --git a/test/SemaTemplate/class-template-id-2.cpp b/test/SemaTemplate/class-template-id-2.cpp index c492a365880c..d09f52476b31 100644 --- a/test/SemaTemplate/class-template-id-2.cpp +++ b/test/SemaTemplate/class-template-id-2.cpp @@ -4,7 +4,7 @@ namespace N { template<> class A<int> { }; - template<> class A<float>; // expected-note{{forward declaration of 'class N::A<float>'}} + template<> class A<float>; // expected-note{{forward declaration of 'N::A<float>'}} class B : public A<int> { }; } diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp index efb00c7f3d25..c65802e5c869 100644 --- a/test/SemaTemplate/class-template-spec.cpp +++ b/test/SemaTemplate/class-template-spec.cpp @@ -20,7 +20,7 @@ int test_incomplete_specs(A<double, double> *a1, A<double> *a2) { (void)a1->x; // expected-error{{member access into incomplete type}} - (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}} + (void)a2->x; // expected-error{{implicit instantiation of undefined template 'A<double, int>'}} } typedef float FLOAT; diff --git a/test/SemaTemplate/default-expr-arguments.cpp b/test/SemaTemplate/default-expr-arguments.cpp index 3da43fa67502..d2cc45b0352b 100644 --- a/test/SemaTemplate/default-expr-arguments.cpp +++ b/test/SemaTemplate/default-expr-arguments.cpp @@ -11,17 +11,17 @@ template<typename T> void f1(T a, T b = 10) { } // expected-error{{no viable con template<typename T> void f2(T a, T b = T()) { } -template<typename T> void f3(T a, T b = T() + T()); // expected-error{{invalid operands to binary expression ('struct S' and 'struct S')}} +template<typename T> void f3(T a, T b = T() + T()); // expected-error{{invalid operands to binary expression ('S' and 'S')}} void g() { f1(10); - f1(S()); // expected-note{{in instantiation of default function argument expression for 'f1<struct S>' required here}} + f1(S()); // expected-note{{in instantiation of default function argument expression for 'f1<S>' required here}} f2(10); f2(S()); f3(10); - f3(S()); // expected-note{{in instantiation of default function argument expression for 'f3<struct S>' required here}} + f3(S()); // expected-note{{in instantiation of default function argument expression for 'f3<S>' required here}} } template<typename T> struct F { @@ -38,10 +38,10 @@ void g2() { void g3(F<int> f, F<struct S> s) { f.f(); - s.f(); // expected-note{{in instantiation of default function argument expression for 'f<struct S>' required here}} + s.f(); // expected-note{{in instantiation of default function argument expression for 'f<S>' required here}} F<int> f2; - F<S> s2; // expected-note{{in instantiation of default function argument expression for 'F<struct S>' required here}} + F<S> s2; // expected-note{{in instantiation of default function argument expression for 'F<S>' required here}} } template<typename T> struct G { diff --git a/test/SemaTemplate/dependent-base-classes.cpp b/test/SemaTemplate/dependent-base-classes.cpp index 08d4de542c6d..600115b56530 100644 --- a/test/SemaTemplate/dependent-base-classes.cpp +++ b/test/SemaTemplate/dependent-base-classes.cpp @@ -32,7 +32,7 @@ namespace PR6031 { template <class TT> struct FI2 { - C<typename FI2::type> a; // expected-error{{no type named 'type' in 'struct PR6031::FI2'}} \ + C<typename FI2::type> a; // expected-error{{no type named 'type' in 'FI2<TT>'}} \ // expected-error{{C++ requires a type specifier for all declarations}} }; @@ -58,7 +58,7 @@ namespace PR6031 { class NoDepBase::Nested nested; // expected-error{{'Nested' does not name a tag member in the specified scope}} typedef typename NoDepBase::template MemberTemplate<T>::type type; // expected-error{{'MemberTemplate' following the 'template' keyword does not refer to a template}} \ // FIXME: expected-error{{unqualified-id}} - return NoDepBase::a; // expected-error{{no member named 'a' in 'struct PR6031::NoDepBase'}} + return NoDepBase::a; // expected-error{{no member named 'a' in 'NoDepBase<T>'}} } }; } diff --git a/test/SemaTemplate/ext-vector-type.cpp b/test/SemaTemplate/ext-vector-type.cpp index 0e2debf22b99..3973102b92e7 100644 --- a/test/SemaTemplate/ext-vector-type.cpp +++ b/test/SemaTemplate/ext-vector-type.cpp @@ -20,7 +20,7 @@ int test_make2() { template<typename T, unsigned Length> struct make3 { - typedef T __attribute__((ext_vector_type(Length))) type; // expected-error{{invalid vector type 'struct s'}} + typedef T __attribute__((ext_vector_type(Length))) type; // expected-error{{invalid vector type 's'}} }; struct s {}; diff --git a/test/SemaTemplate/injected-class-name.cpp b/test/SemaTemplate/injected-class-name.cpp index 482eae14ba59..586be189b0ab 100644 --- a/test/SemaTemplate/injected-class-name.cpp +++ b/test/SemaTemplate/injected-class-name.cpp @@ -42,3 +42,9 @@ struct X1 { void f0(const X1<T, N>&); // expected-error{{redecl}} }; +namespace pr6326 { + template <class T> class A { + friend class A; + }; + template class A<int>; +} diff --git a/test/SemaTemplate/instantiate-cast.cpp b/test/SemaTemplate/instantiate-cast.cpp index 97d3dc30c56c..9669b2035a1f 100644 --- a/test/SemaTemplate/instantiate-cast.cpp +++ b/test/SemaTemplate/instantiate-cast.cpp @@ -23,7 +23,7 @@ struct Constructible { template<typename T, typename U> struct CStyleCast0 { void f(T t) { - (void)((U)t); // expected-error{{C-style cast from 'struct A' to 'int'}} + (void)((U)t); // expected-error{{C-style cast from 'A' to 'int' is not allowed}} } }; @@ -36,7 +36,7 @@ template struct CStyleCast0<A, int>; // expected-note{{instantiation}} template<typename T, typename U> struct StaticCast0 { void f(T t) { - (void)static_cast<U>(t); // expected-error{{static_cast from 'int' to 'struct A' is not allowed}} + (void)static_cast<U>(t); // expected-error{{static_cast from 'int' to 'A' is not allowed}} } }; @@ -89,7 +89,7 @@ template struct ConstCast0<int const *, float *>; // expected-note{{instantiatio template<typename T, typename U> struct FunctionalCast1 { void f(T t) { - (void)U(t); // expected-error{{functional-style cast from 'struct A' to 'int'}} + (void)U(t); // expected-error{{functional-style cast from 'A' to 'int' is not allowed}} } }; diff --git a/test/SemaTemplate/instantiate-complete.cpp b/test/SemaTemplate/instantiate-complete.cpp index 0ae13b972829..82cc320fd3c4 100644 --- a/test/SemaTemplate/instantiate-complete.cpp +++ b/test/SemaTemplate/instantiate-complete.cpp @@ -17,12 +17,12 @@ struct X { X<int> f() { return 0; } struct XField { - X<float(int)> xf; // expected-note{{in instantiation of template class 'struct X<float (int)>' requested here}} + X<float(int)> xf; // expected-note{{in instantiation of template class 'X<float (int)>' requested here}} }; void test_subscript(X<double> *ptr1, X<int(int)> *ptr2, int i) { (void)ptr1[i]; - (void)ptr2[i]; // expected-note{{in instantiation of template class 'struct X<int (int)>' requested here}} + (void)ptr2[i]; // expected-note{{in instantiation of template class 'X<int (int)>' requested here}} } void test_arith(X<signed char> *ptr1, X<unsigned char> *ptr2, @@ -30,13 +30,13 @@ void test_arith(X<signed char> *ptr1, X<unsigned char> *ptr2, (void)(ptr1 + 5); // FIXME: if I drop the ')' after void, below, it still parses (!) (void)(5 + ptr2); - (void)(ptr3 + 5); // expected-note{{in instantiation of template class 'struct X<char (char)>' requested here}} - (void)(5 + ptr4); // expected-note{{in instantiation of template class 'struct X<short (short)>' requested here}} + (void)(ptr3 + 5); // expected-note{{in instantiation of template class 'X<char (char)>' requested here}} + (void)(5 + ptr4); // expected-note{{in instantiation of template class 'X<short (short)>' requested here}} } void test_new() { (void)new X<float>(0); - (void)new X<float(float)>; // expected-note{{in instantiation of template class 'struct X<float (float)>' requested here}} + (void)new X<float(float)>; // expected-note{{in instantiation of template class 'X<float (float)>' requested here}} } void test_memptr(X<long> *p1, long X<long>::*pm1, diff --git a/test/SemaTemplate/instantiate-exception-spec.cpp b/test/SemaTemplate/instantiate-exception-spec.cpp index c418fe16e87f..d4f12df22ec2 100644 --- a/test/SemaTemplate/instantiate-exception-spec.cpp +++ b/test/SemaTemplate/instantiate-exception-spec.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // FIXME: the "note" should be down at the call site! -template<typename T> void f1(T*) throw(T); // expected-error{{incomplete type 'struct Incomplete' is not allowed in exception specification}} \ +template<typename T> void f1(T*) throw(T); // expected-error{{incomplete type 'Incomplete' is not allowed in exception specification}} \ // expected-note{{instantiation of}} struct Incomplete; // expected-note{{forward}} diff --git a/test/SemaTemplate/instantiate-expr-1.cpp b/test/SemaTemplate/instantiate-expr-1.cpp index 37145b63b616..7af59fd2d11b 100644 --- a/test/SemaTemplate/instantiate-expr-1.cpp +++ b/test/SemaTemplate/instantiate-expr-1.cpp @@ -7,7 +7,7 @@ struct Bitfields { void test_Bitfields(Bitfields<0, 5> *b) { (void)sizeof(Bitfields<10, 5>); - (void)sizeof(Bitfields<0, 1>); // expected-note{{in instantiation of template class 'struct Bitfields<0, 1>' requested here}} + (void)sizeof(Bitfields<0, 1>); // expected-note{{in instantiation of template class 'Bitfields<0, 1>' requested here}} } template<int I, int J> @@ -17,7 +17,7 @@ struct BitfieldPlus { void test_BitfieldPlus() { (void)sizeof(BitfieldPlus<0, 1>); - (void)sizeof(BitfieldPlus<-5, 5>); // expected-note{{in instantiation of template class 'struct BitfieldPlus<-5, 5>' requested here}} + (void)sizeof(BitfieldPlus<-5, 5>); // expected-note{{in instantiation of template class 'BitfieldPlus<-5, 5>' requested here}} } template<int I, int J> @@ -28,8 +28,8 @@ struct BitfieldMinus { void test_BitfieldMinus() { (void)sizeof(BitfieldMinus<5, 1>); - (void)sizeof(BitfieldMinus<0, 1>); // expected-note{{in instantiation of template class 'struct BitfieldMinus<0, 1>' requested here}} - (void)sizeof(BitfieldMinus<5, 5>); // expected-note{{in instantiation of template class 'struct BitfieldMinus<5, 5>' requested here}} + (void)sizeof(BitfieldMinus<0, 1>); // expected-note{{in instantiation of template class 'BitfieldMinus<0, 1>' requested here}} + (void)sizeof(BitfieldMinus<5, 5>); // expected-note{{in instantiation of template class 'BitfieldMinus<5, 5>' requested here}} } template<int I, int J> @@ -40,7 +40,7 @@ struct BitfieldDivide { void test_BitfieldDivide() { (void)sizeof(BitfieldDivide<5, 1>); - (void)sizeof(BitfieldDivide<5, 0>); // expected-note{{in instantiation of template class 'struct BitfieldDivide<5, 0>' requested here}} + (void)sizeof(BitfieldDivide<5, 0>); // expected-note{{in instantiation of template class 'BitfieldDivide<5, 0>' requested here}} } template<typename T, T I, int J> @@ -64,9 +64,9 @@ struct BitfieldNeg2 { void test_BitfieldNeg() { (void)sizeof(BitfieldNeg<-5>); // okay - (void)sizeof(BitfieldNeg<5>); // expected-note{{in instantiation of template class 'struct BitfieldNeg<5>' requested here}} + (void)sizeof(BitfieldNeg<5>); // expected-note{{in instantiation of template class 'BitfieldNeg<5>' requested here}} (void)sizeof(BitfieldNeg2<int, -5>); // okay - (void)sizeof(BitfieldNeg2<int, 5>); // expected-note{{in instantiation of template class 'struct BitfieldNeg2<int, 5>' requested here}} + (void)sizeof(BitfieldNeg2<int, 5>); // expected-note{{in instantiation of template class 'BitfieldNeg2<int, 5>' requested here}} } template<typename T> diff --git a/test/SemaTemplate/instantiate-expr-4.cpp b/test/SemaTemplate/instantiate-expr-4.cpp index c5eb3cc53e7a..92915c7daf17 100644 --- a/test/SemaTemplate/instantiate-expr-4.cpp +++ b/test/SemaTemplate/instantiate-expr-4.cpp @@ -153,7 +153,7 @@ struct TypeId0 { if (ptr) return typeid(ptr); else - return typeid(T); // expected-error{{'typeid' of incomplete type 'struct Incomplete'}} + return typeid(T); // expected-error{{'typeid' of incomplete type 'Incomplete'}} } }; diff --git a/test/SemaTemplate/instantiate-field.cpp b/test/SemaTemplate/instantiate-field.cpp index d166e7e78e6a..60d4b21cac9e 100644 --- a/test/SemaTemplate/instantiate-field.cpp +++ b/test/SemaTemplate/instantiate-field.cpp @@ -20,9 +20,9 @@ void test1(const X<int> *xi) { } void test2(const X<float> *xf) { - (void)xf->x; // expected-note{{in instantiation of template class 'struct X<float>' requested here}} + (void)xf->x; // expected-note{{in instantiation of template class 'X<float>' requested here}} } void test3(const X<int(int)> *xf) { - (void)xf->x; // expected-note{{in instantiation of template class 'struct X<int (int)>' requested here}} + (void)xf->x; // expected-note{{in instantiation of template class 'X<int (int)>' requested here}} } diff --git a/test/SemaTemplate/instantiate-function-1.cpp b/test/SemaTemplate/instantiate-function-1.cpp index 144c630fce51..7b4c53cfe0d7 100644 --- a/test/SemaTemplate/instantiate-function-1.cpp +++ b/test/SemaTemplate/instantiate-function-1.cpp @@ -194,7 +194,7 @@ template struct IndirectGoto0<int>; // expected-note{{instantiation}} template<typename T> struct TryCatch0 { void f() { try { - } catch (T t) { // expected-error{{incomplete type}} \ + } catch (T t) { // expected-warning{{incomplete type}} \ // expected-error{{abstract class}} } catch (...) { } diff --git a/test/SemaTemplate/instantiate-member-class.cpp b/test/SemaTemplate/instantiate-member-class.cpp index 742abcc569c2..5d69b50a7606 100644 --- a/test/SemaTemplate/instantiate-member-class.cpp +++ b/test/SemaTemplate/instantiate-member-class.cpp @@ -28,14 +28,14 @@ void test_instantiation(X<double>::C *x, X<float>::D::F *f) { double &dr = x->foo(); float &fr = e->bar(); - f->foo(); // expected-error{{implicit instantiation of undefined member 'struct X<float>::D::F'}} + f->foo(); // expected-error{{implicit instantiation of undefined member 'X<float>::D::F'}} } X<void>::C *c3; // okay X<void>::D::E *e1; // okay -X<void>::D::E e2; // expected-note{{in instantiation of member class 'struct X<void>::D::E' requested here}} +X<void>::D::E e2; // expected-note{{in instantiation of member class 'X<void>::D::E' requested here}} // Redeclarations. namespace test1 { diff --git a/test/SemaTemplate/instantiate-member-expr.cpp b/test/SemaTemplate/instantiate-member-expr.cpp index 324363ce96dc..f3a60679d176 100644 --- a/test/SemaTemplate/instantiate-member-expr.cpp +++ b/test/SemaTemplate/instantiate-member-expr.cpp @@ -16,14 +16,14 @@ public: template <typename CHECKER> void registerCheck(CHECKER *check) { - Checkers.push_back(S<void *>()); // expected-note {{in instantiation of member function 'vector<struct S<void *> >::push_back' requested here}} + Checkers.push_back(S<void *>()); // expected-note {{in instantiation of member function 'vector<S<void *> >::push_back' requested here}} } }; class RetainReleaseChecker { }; void f(GRExprEngine& Eng) { - Eng.registerCheck(new RetainReleaseChecker); // expected-note {{in instantiation of function template specialization 'GRExprEngine::registerCheck<class RetainReleaseChecker>' requested here}} + Eng.registerCheck(new RetainReleaseChecker); // expected-note {{in instantiation of function template specialization 'GRExprEngine::registerCheck<RetainReleaseChecker>' requested here}} } // PR 5838 @@ -43,7 +43,7 @@ namespace test1 { int a; template<typename T> struct B : A<T> { void f() { - a = 0; // expected-error {{type 'struct test1::O' is not a direct or virtual base of ''B<int>''}} + a = 0; // expected-error {{type 'test1::O' is not a direct or virtual base of ''B<int>''}} } }; }; diff --git a/test/SemaTemplate/instantiate-method.cpp b/test/SemaTemplate/instantiate-method.cpp index a02fe5238c35..357ea2617759 100644 --- a/test/SemaTemplate/instantiate-method.cpp +++ b/test/SemaTemplate/instantiate-method.cpp @@ -20,7 +20,7 @@ void test(X<int> *xi, int *ip, X<int(int)> *xf) { } void test_bad() { - X<void> xv; // expected-note{{in instantiation of template class 'class X<void>' requested here}} + X<void> xv; // expected-note{{in instantiation of template class 'X<void>' requested here}} } template<typename T, typename U> @@ -36,7 +36,7 @@ void test_ovl(Overloading<int, long> *oil, int i, long l) { } void test_ovl_bad() { - Overloading<float, float> off; // expected-note{{in instantiation of template class 'class Overloading<float, float>' requested here}} + Overloading<float, float> off; // expected-note{{in instantiation of template class 'Overloading<float, float>' requested here}} } template<typename T> diff --git a/test/SemaTemplate/instantiate-static-var.cpp b/test/SemaTemplate/instantiate-static-var.cpp index fda2b9ea306b..e90ac5223d98 100644 --- a/test/SemaTemplate/instantiate-static-var.cpp +++ b/test/SemaTemplate/instantiate-static-var.cpp @@ -6,7 +6,7 @@ public: }; int array1[X<int, 2>::value == 5? 1 : -1]; -X<int, 0> xi0; // expected-note{{in instantiation of template class 'class X<int, 0>' requested here}} +X<int, 0> xi0; // expected-note{{in instantiation of template class 'X<int, 0>' requested here}} template<typename T> @@ -14,7 +14,7 @@ class Y { static const T value = 0; // expected-error{{'value' can only be initialized if it is a static const integral data member}} }; -Y<float> fy; // expected-note{{in instantiation of template class 'class Y<float>' requested here}} +Y<float> fy; // expected-note{{in instantiation of template class 'Y<float>' requested here}} // out-of-line static member variables diff --git a/test/SemaTemplate/instantiate-typedef.cpp b/test/SemaTemplate/instantiate-typedef.cpp index 977fd08cc36d..bb168a1c932e 100644 --- a/test/SemaTemplate/instantiate-typedef.cpp +++ b/test/SemaTemplate/instantiate-typedef.cpp @@ -11,6 +11,6 @@ add_pointer<float>::type test2(int * ptr) { return ptr; // expected-error{{cannot initialize return object of type 'add_pointer<float>::type' (aka 'float *') with an lvalue of type 'int *'}} } -add_pointer<int&>::type // expected-note{{in instantiation of template class 'struct add_pointer<int &>' requested here}} \ -// expected-error {{no type named 'type' in 'struct add_pointer<int &>'}} +add_pointer<int&>::type // expected-note{{in instantiation of template class 'add_pointer<int &>' requested here}} \ +// expected-error {{no type named 'type' in 'add_pointer<int &>'}} test3(); diff --git a/test/SemaTemplate/instantiation-backtrace.cpp b/test/SemaTemplate/instantiation-backtrace.cpp index 93f9a3552aa0..21456e902ae5 100644 --- a/test/SemaTemplate/instantiation-backtrace.cpp +++ b/test/SemaTemplate/instantiation-backtrace.cpp @@ -2,7 +2,7 @@ template<typename T> struct A; // expected-note 4{{template is declared here}} template<typename T> struct B : A<T*> { }; // expected-error{{implicit instantiation of undefined template}} \ -// expected-error{{implicit instantiation of undefined template 'struct A<X *>'}} +// expected-error{{implicit instantiation of undefined template 'A<X *>'}} template<typename T> struct C : B<T> { } ; // expected-note{{instantiation of template class}} @@ -19,14 +19,14 @@ void f() { typedef struct { } X; void g() { - (void)sizeof(B<X>); // expected-note{{in instantiation of template class 'struct B<X>' requested here}} + (void)sizeof(B<X>); // expected-note{{in instantiation of template class 'B<X>' requested here}} } template<typename T> -struct G : A<T>, // expected-error{{implicit instantiation of undefined template 'struct A<int>'}} - A<T*> // expected-error{{implicit instantiation of undefined template 'struct A<int *>'}} +struct G : A<T>, // expected-error{{implicit instantiation of undefined template 'A<int>'}} + A<T*> // expected-error{{implicit instantiation of undefined template 'A<int *>'}} { }; void h() { - (void)sizeof(G<int>); // expected-note{{in instantiation of template class 'struct G<int>' requested here}} + (void)sizeof(G<int>); // expected-note{{in instantiation of template class 'G<int>' requested here}} } diff --git a/test/SemaTemplate/metafun-apply.cpp b/test/SemaTemplate/metafun-apply.cpp index bb3c88ad3957..3a7408e28025 100644 --- a/test/SemaTemplate/metafun-apply.cpp +++ b/test/SemaTemplate/metafun-apply.cpp @@ -22,7 +22,7 @@ struct bogus { template<typename MetaFun, typename T> struct apply1 { - typedef typename MetaFun::template apply<T>::type type; // expected-note{{in instantiation of template class 'struct add_reference::apply<void>' requested here}} \ + typedef typename MetaFun::template apply<T>::type type; // expected-note{{in instantiation of template class 'add_reference::apply<void>' requested here}} \ // expected-error{{'apply' following the 'template' keyword does not refer to a template}} }; @@ -32,9 +32,9 @@ apply1<add_reference, int>::type ir = i; apply1<add_reference, float>::type fr = i; // expected-error{{non-const lvalue reference to type 'float' cannot bind to a value of unrelated type 'int'}} void test() { - apply1<add_reference, void>::type t; // expected-note{{in instantiation of template class 'struct apply1<struct add_reference, void>' requested here}} + apply1<add_reference, void>::type t; // expected-note{{in instantiation of template class 'apply1<add_reference, void>' requested here}} - apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'struct apply1<struct bogus, int>' requested here}} + apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'apply1<bogus, int>' requested here}} } diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp index fdfd4e47b240..9c20f2a0eb1e 100644 --- a/test/SemaTemplate/temp_arg_nontype.cpp +++ b/test/SemaTemplate/temp_arg_nontype.cpp @@ -16,7 +16,7 @@ enum E { Enumerator = 17 }; A<E> *a5; // expected-error{{template argument for non-type template parameter must be an expression}} template<E Value> struct A1; // expected-note{{template parameter is declared here}} A1<Enumerator> *a6; // okay -A1<17> *a7; // expected-error{{non-type template argument of type 'int' cannot be converted to a value of type 'enum E'}} +A1<17> *a7; // expected-error{{non-type template argument of type 'int' cannot be converted to a value of type 'E'}} const long LongValue = 12345678; A<LongValue> *a8; @@ -32,7 +32,7 @@ public: X(int, int); operator int() const; }; -A<X(17, 42)> *a11; // expected-error{{non-type template argument of type 'class X' must have an integral or enumeration type}} +A<X(17, 42)> *a11; // expected-error{{non-type template argument of type 'X' must have an integral or enumeration type}} float f(float); @@ -59,8 +59,8 @@ volatile X * X_volatile_ptr; template<X const &AnX> struct A4; // expected-note 2{{template parameter is declared here}} X an_X; A4<an_X> *a15_1; // okay -A4<*X_volatile_ptr> *a15_2; // expected-error{{reference binding of non-type template parameter of type 'class X const &' to template argument of type 'class X volatile' ignores qualifiers}} -A4<y> *15_3; // expected-error{{non-type template parameter of reference type 'class X const &' cannot bind to template argument of type 'struct Y'}} \ +A4<*X_volatile_ptr> *a15_2; // expected-error{{reference binding of non-type template parameter of type 'X const &' to template argument of type 'X volatile' ignores qualifiers}} +A4<y> *15_3; // expected-error{{non-type template parameter of reference type 'X const &' cannot bind to template argument of type 'struct Y'}} \ // FIXME: expected-error{{expected unqualified-id}} template<int (&fr)(int)> struct A5; // expected-note 2{{template parameter is declared here}} @@ -83,14 +83,14 @@ struct Z { template<int (Z::*pmf)(int)> struct A6; // expected-note{{template parameter is declared here}} A6<&Z::foo> *a17_1; A6<&Z::bar> *a17_2; -A6<&Z::baz> *a17_3; // expected-error{{non-type template argument of type 'double (struct Z::*)(double)' cannot be converted to a value of type 'int (struct Z::*)(int)'}} +A6<&Z::baz> *a17_3; // expected-error{{non-type template argument of type 'double (Z::*)(double)' cannot be converted to a value of type 'int (Z::*)(int)'}} template<int Z::*pm> struct A7; // expected-note{{template parameter is declared here}} template<int Z::*pm> struct A7c; A7<&Z::int_member> *a18_1; A7c<&Z::int_member> *a18_2; -A7<&Z::float_member> *a18_3; // expected-error{{non-type template argument of type 'float struct Z::*' cannot be converted to a value of type 'int struct Z::*'}} +A7<&Z::float_member> *a18_3; // expected-error{{non-type template argument of type 'float Z::*' cannot be converted to a value of type 'int Z::*'}} A7c<(&Z::int_member)> *a18_3; // expected-error{{non-type template argument cannot be surrounded by parentheses}} template<unsigned char C> struct Overflow; // expected-note{{template parameter is declared here}} diff --git a/test/SemaTemplate/temp_arg_type.cpp b/test/SemaTemplate/temp_arg_type.cpp index a376900666d8..a1db3f8057ac 100644 --- a/test/SemaTemplate/temp_arg_type.cpp +++ b/test/SemaTemplate/temp_arg_type.cpp @@ -14,7 +14,7 @@ A<A<int> > *a6; // [temp.arg.type]p2 void f() { class X { }; - A<X> * a = 0; // expected-error{{template argument uses local type 'class X'}} + A<X> * a = 0; // expected-error{{template argument uses local type 'X'}} } struct { int x; } Unnamed; // expected-note{{unnamed type used in template argument was declared here}} diff --git a/test/SemaTemplate/typename-specifier-4.cpp b/test/SemaTemplate/typename-specifier-4.cpp index 0a6fef74c340..280a1b4c3957 100644 --- a/test/SemaTemplate/typename-specifier-4.cpp +++ b/test/SemaTemplate/typename-specifier-4.cpp @@ -99,3 +99,20 @@ namespace PR6268 { return Inner<U>(); } } + +namespace PR6463 { + struct B { typedef int type; }; // expected-note 2{{member found by ambiguous name lookup}} + struct C { typedef int type; }; // expected-note 2{{member found by ambiguous name lookup}} + + template<typename T> + struct A : B, C { + type& a(); // expected-error{{found in multiple base classes}} + int x; + }; + + // FIXME: Improve source location info here. + template<typename T> + typename A<T>::type& A<T>::a() { // expected-error{{found in multiple base classes}} + return x; // expected-error{{undeclared identifier}} + } +} diff --git a/test/SemaTemplate/typename-specifier.cpp b/test/SemaTemplate/typename-specifier.cpp index b968ea6ad544..42766a0620b8 100644 --- a/test/SemaTemplate/typename-specifier.cpp +++ b/test/SemaTemplate/typename-specifier.cpp @@ -16,7 +16,7 @@ namespace N { int i; typename N::A::type *ip1 = &i; -typename N::B::type *ip2 = &i; // expected-error{{no type named 'type' in 'struct N::B'}} +typename N::B::type *ip2 = &i; // expected-error{{no type named 'type' in 'N::B'}} typename N::C::type *ip3 = &i; // expected-error{{typename specifier refers to non-type member 'type'}} void test(double d) { @@ -33,8 +33,8 @@ void test(double d) { namespace N { template<typename T> struct X { - typedef typename T::type type; // expected-error {{no type named 'type' in 'struct N::B'}} \ - // expected-error {{no type named 'type' in 'struct B'}} \ + typedef typename T::type type; // expected-error {{no type named 'type' in 'N::B'}} \ + // expected-error {{no type named 'type' in 'B'}} \ // FIXME: location info for error above isn't very good \ // expected-error 2{{typename specifier refers to non-type member 'type'}} \ // expected-error{{type 'int' cannot be used prior to '::' because it has no members}} @@ -42,18 +42,18 @@ namespace N { } N::X<N::A>::type *ip4 = &i; -N::X<N::B>::type *ip5 = &i; // expected-note{{in instantiation of template class 'struct N::X<struct N::B>' requested here}} \ +N::X<N::B>::type *ip5 = &i; // expected-note{{in instantiation of template class 'N::X<N::B>' requested here}} \ // expected-error{{no type named 'type' in}} -N::X<N::C>::type *ip6 = &i; // expected-note{{in instantiation of template class 'struct N::X<struct N::C>' requested here}} \ +N::X<N::C>::type *ip6 = &i; // expected-note{{in instantiation of template class 'N::X<N::C>' requested here}} \ // expected-error{{no type named 'type' in}} -N::X<int>::type fail1; // expected-note{{in instantiation of template class 'struct N::X<int>' requested here}} \ +N::X<int>::type fail1; // expected-note{{in instantiation of template class 'N::X<int>' requested here}} \ // expected-error{{no type named 'type' in}} template<typename T> struct Y { - typedef typename N::X<T>::type *type; // expected-note{{in instantiation of template class 'struct N::X<struct B>' requested here}} \ - // expected-note{{in instantiation of template class 'struct N::X<struct C>' requested here}} + typedef typename N::X<T>::type *type; // expected-note{{in instantiation of template class 'N::X<B>' requested here}} \ + // expected-note{{in instantiation of template class 'N::X<C>' requested here}} }; struct A { @@ -69,7 +69,7 @@ struct C { }; ::Y<A>::type ip7 = &i; -::Y<B>::type ip8 = &i; // expected-note{{in instantiation of template class 'struct Y<struct B>' requested here}} \ +::Y<B>::type ip8 = &i; // expected-note{{in instantiation of template class 'Y<B>' requested here}} \ // expected-error{{no type named 'type' in}} -::Y<C>::type ip9 = &i; // expected-note{{in instantiation of template class 'struct Y<struct C>' requested here}} \ +::Y<C>::type ip9 = &i; // expected-note{{in instantiation of template class 'Y<C>' requested here}} \ // expected-error{{no type named 'type' in}} diff --git a/test/SemaTemplate/virtual-member-functions.cpp b/test/SemaTemplate/virtual-member-functions.cpp index 58ac08c0b21b..8df808d2569a 100644 --- a/test/SemaTemplate/virtual-member-functions.cpp +++ b/test/SemaTemplate/virtual-member-functions.cpp @@ -14,7 +14,7 @@ template<class T> int A<T>::a(T x) { } void f(A<int> x) { - x.anchor(); // expected-note{{in instantiation of member function 'PR5557::A<int>::anchor' requested here}} + x.anchor(); } template<typename T> @@ -52,4 +52,4 @@ T *HasOutOfLineKey<T>::f(float *fp) { return fp; // expected-error{{cannot initialize return object of type 'int *' with an lvalue of type 'float *'}} } -HasOutOfLineKey<int> out_of_line; // expected-note{{in instantiation of member function 'HasOutOfLineKey<int>::HasOutOfLineKey' requested here}} +HasOutOfLineKey<int> out_of_line; diff --git a/test/lit.cfg b/test/lit.cfg index 3565edc779b8..beb8ae03b4f6 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -97,18 +97,6 @@ if config.test_exec_root is None: ### -import re -site_exp = {} -for line in open(os.path.join(config.llvm_obj_root, 'test', 'site.exp')): - m = re.match('set ([^ ]+) "([^"]*)"', line) - if m: - site_exp[m.group(1)] = m.group(2) - -targets = set(site_exp['TARGETS_TO_BUILD'].split()) -def llvm_supports_target(name): - return name in targets -config.conditions['TARGET'] = llvm_supports_target - # Discover the 'clang' and 'clangcc' to use. import os diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index 07bb7fbd83ef..b52a32ed9b51 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -315,6 +315,7 @@ public: bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); bool VisitExplicitCastExpr(ExplicitCastExpr *E); bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E); + bool VisitObjCMessageExpr(ObjCMessageExpr *E); }; } // end anonymous namespace @@ -532,9 +533,10 @@ bool CursorVisitor::VisitVarDecl(VarDecl *D) { } bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) { - // FIXME: We really need a TypeLoc covering Objective-C method declarations. - // At the moment, we don't have information about locations in the return - // type. + if (TypeSourceInfo *TSInfo = ND->getResultTypeSourceInfo()) + if (Visit(TSInfo->getTypeLoc())) + return true; + for (ObjCMethodDecl::param_iterator P = ND->param_begin(), PEnd = ND->param_end(); P != PEnd; ++P) { @@ -900,6 +902,14 @@ bool CursorVisitor::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { return VisitExpr(E); } +bool CursorVisitor::VisitObjCMessageExpr(ObjCMessageExpr *E) { + ObjCMessageExpr::ClassInfo CI = E->getClassInfo(); + if (CI.Decl && Visit(MakeCursorObjCClassRef(CI.Decl, CI.Loc, TU))) + return true; + + return VisitExpr(E); +} + bool CursorVisitor::VisitAttributes(Decl *D) { for (const Attr *A = D->getAttrs(); A; A = A->getNext()) if (Visit(MakeCXCursor(A, D, TU))) @@ -1579,6 +1589,18 @@ unsigned clang_isTranslationUnit(enum CXCursorKind K) { return K == CXCursor_TranslationUnit; } +unsigned clang_isUnexposed(enum CXCursorKind K) { + switch (K) { + case CXCursor_UnexposedDecl: + case CXCursor_UnexposedExpr: + case CXCursor_UnexposedStmt: + case CXCursor_UnexposedAttr: + return true; + default: + return false; + } +} + CXCursorKind clang_getCursorKind(CXCursor C) { return C.kind; } diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports index e68060b27de2..5b9530052b51 100644 --- a/tools/CIndex/CIndex.exports +++ b/tools/CIndex/CIndex.exports @@ -67,6 +67,7 @@ _clang_isInvalid _clang_isReference _clang_isStatement _clang_isTranslationUnit +_clang_isUnexposed _clang_setUseExternalASTGeneration _clang_tokenize _clang_visitChildren diff --git a/tools/Makefile b/tools/Makefile index ce3e4cd308e4..5a9c67421b78 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -10,4 +10,11 @@ LEVEL := ../../.. DIRS := driver CIndex c-index-test +include $(LEVEL)/Makefile.config + +ifeq ($(OS), $(filter $(OS), Cygwin MingW)) +DIRS := $(filter $(DIRS), CIndex) +DIRS := $(filter $(DIRS), c-index-test) +endif + include $(LEVEL)/Makefile.common diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp index fa0f0c2ded4e..46f412403167 100644 --- a/tools/driver/driver.cpp +++ b/tools/driver/driver.cpp @@ -194,9 +194,9 @@ int main(int argc, const char **argv) { Diagnostic Diags(&DiagClient); #ifdef CLANG_IS_PRODUCTION - bool IsProduction = true; + const bool IsProduction = true; #else - bool IsProduction = false; + const bool IsProduction = false; #endif Driver TheDriver(Path.getBasename(), Path.getDirname(), llvm::sys::getHostTriple(), diff --git a/tools/scan-build/ccc-analyzer b/tools/scan-build/ccc-analyzer index e3db5eab326e..daf5f7f9ef48 100755 --- a/tools/scan-build/ccc-analyzer +++ b/tools/scan-build/ccc-analyzer @@ -380,13 +380,20 @@ my %UniqueOptions = ( '-isysroot' => 0 ); +##----------------------------------------------------------------------------## +# Languages accepted. +##----------------------------------------------------------------------------## + my %LangsAccepted = ( "objective-c" => 1, - "c" => 1, - "c++" => 1, - "objective-c++" => 1 + "c" => 1 ); +if (defined $ENV{'CCC_ANALYZER_CPLUSPLUS'}) { + $LangsAccepted{"c++"} = 1; + $LangsAccepted{"objective-c++"} = 1; +} + ##----------------------------------------------------------------------------## # Main Logic. ##----------------------------------------------------------------------------## |