diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index d24f00694f7f7aff3068b913cbc0b2557acc6067..d6b5c968a354c41aed113b738cafbdb91c64dcb9 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -192,6 +192,7 @@ class ASTContext : public RefCountedBase { mutable llvm::FoldingSet ComplexTypes; mutable llvm::FoldingSet PointerTypes; mutable llvm::FoldingSet AdjustedTypes; + mutable llvm::FoldingSet ThisTypes; mutable llvm::FoldingSet BlockPointerTypes; mutable llvm::FoldingSet LValueReferenceTypes; mutable llvm::FoldingSet RValueReferenceTypes; @@ -447,7 +448,7 @@ public: using TemplateOrSpecializationInfo = llvm::PointerUnion; - mutable llvm::DenseMap BSCDeclContextMap; + mutable llvm::DenseMap BSCDeclContextMap; private: friend class ASTDeclReader; @@ -981,6 +982,7 @@ public: CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99. CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99. CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; + CanQualType ThisTy; CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; CanQualType UnsignedLongLongTy, UnsignedInt128Ty; CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty; @@ -1221,6 +1223,8 @@ public: getAdjustedType((QualType)Orig, (QualType)New)); } + QualType getThisType(QualType T) const; + /// Return the uniqued reference to the decayed version of the given /// type. Can only be called on array and function types which decay to /// pointer types. @@ -1449,6 +1453,8 @@ public: QualType getEnumType(const EnumDecl *Decl) const; + QualType getInterfaceType(const InterfaceDecl *Decl) const; + QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const; QualType getAttributedType(attr::Kind attrKind, diff --git a/clang/include/clang/AST/BuiltinTypes.def b/clang/include/clang/AST/BuiltinTypes.def index 039765dfdfea67d37de3e11c23c47d091e82e1c9..c02ff239601dcf56009dcedd8f1886fc0797669b 100644 --- a/clang/include/clang/AST/BuiltinTypes.def +++ b/clang/include/clang/AST/BuiltinTypes.def @@ -74,6 +74,8 @@ SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(WChar_U, WCharTy)) // 'char8_t' in C++20 (proposed) UNSIGNED_TYPE(Char8, Char8Ty) +UNSIGNED_TYPE(This, ThisTy) + // 'char16_t' in C++ UNSIGNED_TYPE(Char16, Char16Ty) diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 1e54e91736a3171cb5b838f9625bc1007af6ed74..cb03c816911e4a1e56e343812bfc4d5e1c5c6449 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -1645,7 +1645,7 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; - bool isThisParam = false; + bool IsThisParam = false; void setObjCMethodScopeInfo(unsigned parameterIndex) { ParmVarDeclBits.IsObjCMethodParam = true; @@ -3472,6 +3472,7 @@ public: bool isClass() const { return getTagKind() == TTK_Class; } bool isUnion() const { return getTagKind() == TTK_Union; } bool isEnum() const { return getTagKind() == TTK_Enum; } + bool isInterfaceBSC() const { return getTagKind() == TTK_Interface_bsc; } /// Is this tag type named, either directly or via being defined in /// a typedef of this type? @@ -4072,6 +4073,245 @@ private: void LoadFieldsFromExternalStorage() const; }; +class InterfaceDecl : public TagDecl { + // This class stores some data in DeclContext::RecordDeclBits + // to save some space. Use the provided accessors to access it. +public: + friend class DeclContext; + /// Enum that represents the different ways arguments are passed to and + /// returned from function calls. This takes into account the target-specific + /// and version-specific rules along with the rules determined by the + /// language. + enum ArgPassingKind : unsigned { + /// The argument of this type can be passed directly in registers. + APK_CanPassInRegs, + + /// The argument of this type cannot be passed directly in registers. + /// Records containing this type as a subobject are not forced to be passed + /// indirectly. This value is used only in C++. This value is required by + /// C++ because, in uncommon situations, it is possible for a class to have + /// only trivial copy/move constructors even when one of its subobjects has + /// a non-trivial copy/move constructor (if e.g. the corresponding copy/move + /// constructor in the derived class is deleted). + APK_CannotPassInRegs, + + /// The argument of this type cannot be passed directly in registers. + /// Records containing this type as a subobject are forced to be passed + /// indirectly. + APK_CanNeverPassInRegs + }; + +protected: + InterfaceDecl(Kind DK, TagKind TK, const ASTContext &C, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + InterfaceDecl *PrevDecl); + +public: + static InterfaceDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, InterfaceDecl* PrevDecl = nullptr); + static InterfaceDecl *CreateDeserialized(const ASTContext &C, unsigned ID); + + InterfaceDecl *getPreviousDecl() { + return cast_or_null( + static_cast(this)->getPreviousDecl()); + } + const InterfaceDecl *getPreviousDecl() const { + return const_cast(this)->getPreviousDecl(); + } + + InterfaceDecl *getMostRecentDecl() { + return cast(static_cast(this)->getMostRecentDecl()); + } + const InterfaceDecl *getMostRecentDecl() const { + return const_cast(this)->getMostRecentDecl(); + } + + bool hasFlexibleArrayMember() const { + return InterfaceDeclBits.HasFlexibleArrayMember; + } + + void setHasFlexibleArrayMember(bool V) { + InterfaceDeclBits.HasFlexibleArrayMember = V; + } + + /// Whether this is an anonymous struct or union. To be an anonymous + /// struct or union, it must have been declared without a name and + /// there must be no objects of this type declared, e.g., + /// @code + /// union { int i; float f; }; + /// @endcode + /// is an anonymous union but neither of the following are: + /// @code + /// union X { int i; float f; }; + /// union { int i; float f; } obj; + /// @endcode + bool isAnonymousStructOrUnion() const { + return InterfaceDeclBits.AnonymousStructOrUnion; + } + + void setAnonymousStructOrUnion(bool Anon) { + InterfaceDeclBits.AnonymousStructOrUnion = Anon; + } + + bool hasObjectMember() const { return InterfaceDeclBits.HasObjectMember; } + void setHasObjectMember(bool val) { InterfaceDeclBits.HasObjectMember = val; } + + bool hasVolatileMember() const { return InterfaceDeclBits.HasVolatileMember; } + + void setHasVolatileMember(bool val) { + InterfaceDeclBits.HasVolatileMember = val; + } + + bool hasLoadedFieldsFromExternalStorage() const { + return InterfaceDeclBits.LoadedFieldsFromExternalStorage; + } + + void setHasLoadedFieldsFromExternalStorage(bool val) const { + InterfaceDeclBits.LoadedFieldsFromExternalStorage = val; + } + + /// Functions to query basic properties of non-trivial C structs. + bool isNonTrivialToPrimitiveDefaultInitialize() const { + return InterfaceDeclBits.NonTrivialToPrimitiveDefaultInitialize; + } + + void setNonTrivialToPrimitiveDefaultInitialize(bool V) { + InterfaceDeclBits.NonTrivialToPrimitiveDefaultInitialize = V; + } + + bool isNonTrivialToPrimitiveCopy() const { + return InterfaceDeclBits.NonTrivialToPrimitiveCopy; + } + + void setNonTrivialToPrimitiveCopy(bool V) { + InterfaceDeclBits.NonTrivialToPrimitiveCopy = V; + } + + bool isNonTrivialToPrimitiveDestroy() const { + return InterfaceDeclBits.NonTrivialToPrimitiveDestroy; + } + + void setNonTrivialToPrimitiveDestroy(bool V) { + InterfaceDeclBits.NonTrivialToPrimitiveDestroy = V; + } + + bool hasNonTrivialToPrimitiveDefaultInitializeCUnion() const { + return InterfaceDeclBits.HasNonTrivialToPrimitiveDefaultInitializeCUnion; + } + + void setHasNonTrivialToPrimitiveDefaultInitializeCUnion(bool V) { + InterfaceDeclBits.HasNonTrivialToPrimitiveDefaultInitializeCUnion = V; + } + + bool hasNonTrivialToPrimitiveDestructCUnion() const { + return InterfaceDeclBits.HasNonTrivialToPrimitiveDestructCUnion; + } + + void setHasNonTrivialToPrimitiveDestructCUnion(bool V) { + InterfaceDeclBits.HasNonTrivialToPrimitiveDestructCUnion = V; + } + + bool hasNonTrivialToPrimitiveCopyCUnion() const { + return InterfaceDeclBits.HasNonTrivialToPrimitiveCopyCUnion; + } + + void setHasNonTrivialToPrimitiveCopyCUnion(bool V) { + InterfaceDeclBits.HasNonTrivialToPrimitiveCopyCUnion = V; + } + + using field_iterator = specific_decl_iterator; + using field_range = llvm::iterator_range>; + + bool isOrContainsUnion() const; + + field_range fields() const { return field_range(field_begin(), field_end()); } + field_iterator field_begin() const; + + field_iterator field_end() const { + return field_iterator(decl_iterator()); + } + + // Whether there are any fields (non-static data members) in this record. + bool field_empty() const { + return field_begin() == field_end(); + } + + /// Determine whether this class can be passed in registers. In C++ mode, + /// it must have at least one trivial, non-deleted copy or move constructor. + /// FIXME: This should be set as part of completeDefinition. + virtual void completeDefinition(); + + bool canPassInRegisters() const { + return getArgPassingRestrictions() == APK_CanPassInRegs; + } + + ArgPassingKind getArgPassingRestrictions() const { + return static_cast(InterfaceDeclBits.ArgPassingRestrictions); + } + + void setArgPassingRestrictions(ArgPassingKind Kind) { + InterfaceDeclBits.ArgPassingRestrictions = Kind; + } + + bool isParamDestroyedInCallee() const { + return InterfaceDeclBits.ParamDestroyedInCallee; + } + + void setParamDestroyedInCallee(bool V) { + InterfaceDeclBits.ParamDestroyedInCallee = V; + } + + bool isInjectedClassName() const; + + /// Determine whether this record is a class describing a lambda + /// function object. + bool isLambda() const; + + /// Determine whether this record is a record for captured variables in + /// CapturedStmt construct. + bool isCapturedRecord() const; + + /// Mark the record as a record for captured variables in CapturedStmt + /// construct. + void setCapturedRecord(); + + /// Returns the RecordDecl that actually defines + /// this struct/union/class. When determining whether or not a + /// struct/union/class is completely defined, one should use this + /// method as opposed to 'isCompleteDefinition'. + /// 'isCompleteDefinition' indicates whether or not a specific + /// RecordDecl is a completed definition, not whether or not the + /// record type is defined. This method returns NULL if there is + /// no RecordDecl that defines the struct/union/tag. + InterfaceDecl *getDefinition() const { + return cast_or_null(TagDecl::getDefinition()); + } + + + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { + return K == Interface; + } + + bool isMsStruct(const ASTContext &C) const; + + /// Whether we are allowed to insert extra padding between fields. + /// These padding are added to help AddressSanitizer detect + /// intra-object-overflow bugs. + bool mayInsertExtraPadding(bool EmitRemark = false) const; + + /// Finds the first data member which has a name. + /// nullptr is returned if no named data member exists. + const FieldDecl *findFirstNamedDataMember() const; + +private: + /// Deserialize just the fields. + void LoadFieldsFromExternalStorage() const; +}; + class FileScopeAsmDecl : public Decl { StringLiteral *AsmString; SourceLocation RParenLoc; diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index e0a75d099fbe9e34387490b5662070b70cfd34e5..6b8187dd674304f5b68724c4241363e764796da6 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -1488,6 +1488,60 @@ class DeclContext { /// Number of non-inherited bits in RecordDeclBitfields. enum { NumRecordDeclBits = 14 }; + /// Stores the bits used by RecordDecl. + /// If modified NumRecordDeclBits and the accessor + /// methods in RecordDecl should be updated appropriately. + class InterfaceDeclBitfields { + friend class InterfaceDecl; + /// For the bits in DeclContextBitfields. + uint64_t : NumDeclContextBits; + /// For the bits in TagDeclBitfields. + uint64_t : NumTagDeclBits; + + /// This is true if this struct ends with a flexible + /// array member (e.g. int X[]) or if this union contains a struct that does. + /// If so, this cannot be contained in arrays or other structs as a member. + uint64_t HasFlexibleArrayMember : 1; + + /// Whether this is the type of an anonymous struct or union. + uint64_t AnonymousStructOrUnion : 1; + + /// This is true if this struct has at least one member + /// containing an Objective-C object pointer type. + uint64_t HasObjectMember : 1; + + /// This is true if struct has at least one member of + /// 'volatile' type. + uint64_t HasVolatileMember : 1; + + /// Whether the field declarations of this record have been loaded + /// from external storage. To avoid unnecessary deserialization of + /// methods/nested types we allow deserialization of just the fields + /// when needed. + mutable uint64_t LoadedFieldsFromExternalStorage : 1; + + /// Basic properties of non-trivial C structs. + uint64_t NonTrivialToPrimitiveDefaultInitialize : 1; + uint64_t NonTrivialToPrimitiveCopy : 1; + uint64_t NonTrivialToPrimitiveDestroy : 1; + + /// The following bits indicate whether this is or contains a C union that + /// is non-trivial to default-initialize, destruct, or copy. These bits + /// imply the associated basic non-triviality predicates declared above. + uint64_t HasNonTrivialToPrimitiveDefaultInitializeCUnion : 1; + uint64_t HasNonTrivialToPrimitiveDestructCUnion : 1; + uint64_t HasNonTrivialToPrimitiveCopyCUnion : 1; + + /// Indicates whether this struct is destroyed in the callee. + uint64_t ParamDestroyedInCallee : 1; + + /// Represents the way this type is passed to a function. + uint64_t ArgPassingRestrictions : 2; + }; + + /// Number of non-inherited bits in RecordDeclBitfields. + enum { NumInterfaceDeclBits = 14 }; + /// Stores the bits used by OMPDeclareReductionDecl. /// If modified NumOMPDeclareReductionDeclBits and the accessor /// methods in OMPDeclareReductionDecl should be updated appropriately. @@ -1761,6 +1815,7 @@ protected: ObjCContainerDeclBitfields ObjCContainerDeclBits; LinkageSpecDeclBitfields LinkageSpecDeclBits; BlockDeclBitfields BlockDeclBits; + InterfaceDeclBitfields InterfaceDeclBits; static_assert(sizeof(DeclContextBitfields) <= 8, "DeclContextBitfields is larger than 8 bytes!"); @@ -1898,6 +1953,10 @@ public: getDeclKind() <= Decl::lastRecord; } + bool isInterface() const { + return getDeclKind() == Decl::Interface; + } + bool isNamespace() const { return getDeclKind() == Decl::Namespace; } bool isStdNamespace() const; diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 5da1097e8a7a0ad208fc8cda5fdd813a7a6c3c45..58ba43559e0ef5170366de6aefd5eb2a4ac32f15 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1945,21 +1945,19 @@ protected: } public: - static BSCMethodDecl *Create(ASTContext &C, DeclContext *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, StorageClass SC, - bool isInline, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, - Expr *TrailingRequiresClause = nullptr); + static BSCMethodDecl * + Create(ASTContext &C, DeclContext *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + StorageClass SC, bool isInline, ConstexprSpecKind ConstexprKind, + SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr); static BSCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); - bool getHasThisParam() const { - return hasThisParam; - } - void setHasThisParam(bool hasThisParam) { this->hasThisParam = hasThisParam; } + bool getHasThisParam() const { return HasThisParam; } + void setHasThisParam(bool HasThisParam) { this->HasThisParam = HasThisParam; } QualType getExtendedType() const { return ExtendedType; } - void setExtendedType(QualType ExtendedType) { this->ExtendedType = ExtendedType; } + void setExtendedType(QualType ExtendedType) { + this->ExtendedType = ExtendedType; + } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -1967,7 +1965,7 @@ public: private: QualType ExtendedType; - bool hasThisParam = false; + bool HasThisParam = false; }; /// Represents a static or instance method of a struct/union/class. diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index a44d06967431ad0c366a5f2e2db62e468511477a..b19f98326eeba639d34e741d20bb446fd170ed0d 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -138,6 +138,7 @@ protected: friend class ASTStmtReader; // Sets dependence dircetly. public: + bool HasBSCScopeSpce = false; QualType getType() const { return TR; } void setType(QualType t) { // In C++, the type of an expression is always adjusted so that it diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 55f3253e6920bb8a9da5bc660beee7a3421da3a7..aac16cba7d550e0e62296c82816b3aabf1ac01cf 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -485,6 +485,7 @@ private: unsigned Count); bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); bool TraverseRecordHelper(RecordDecl *D); + bool TraverseInterfaceHelper(InterfaceDecl *D); bool TraverseCXXRecordHelper(CXXRecordDecl *D); bool TraverseDeclaratorHelper(DeclaratorDecl *D); bool TraverseDeclContextHelper(DeclContext *DC); @@ -882,6 +883,7 @@ RecursiveASTVisitor::TraverseLambdaCapture(LambdaExpr *LE, } DEF_TRAVERSE_TYPE(BuiltinType, {}) +DEF_TRAVERSE_TYPE(ThisType, {}) DEF_TRAVERSE_TYPE(ComplexType, { TRY_TO(TraverseType(T->getElementType())); }) @@ -1004,6 +1006,7 @@ DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, { }) DEF_TRAVERSE_TYPE(RecordType, {}) +DEF_TRAVERSE_TYPE(InterfaceType, {}) DEF_TRAVERSE_TYPE(EnumType, {}) DEF_TRAVERSE_TYPE(TemplateTypeParmType, {}) DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, { @@ -1084,7 +1087,7 @@ DEF_TRAVERSE_TYPE(DependentExtIntType, bool RecursiveASTVisitor::Traverse##TYPE##Loc(TYPE##Loc TL) { \ if (!getDerived().shouldTraversePostOrder()) { \ TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ - if (getDerived().shouldWalkTypesOfTypeLocs()) \ + if (getDerived().shouldWalkTypesOfTypeLocs()) \ TRY_TO(WalkUpFrom##TYPE(const_cast(TL.getTypePtr()))); \ } \ { CODE; } \ @@ -1119,6 +1122,7 @@ RecursiveASTVisitor::TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) { DEF_TRAVERSE_TYPELOC(BuiltinType, {}) + // FIXME: ComplexTypeLoc is unfinished DEF_TRAVERSE_TYPELOC(ComplexType, { TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); @@ -1248,6 +1252,7 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, { DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {}) DEF_TRAVERSE_TYPELOC(TypedefType, {}) +DEF_TRAVERSE_TYPELOC(ThisType, {}) DEF_TRAVERSE_TYPELOC(TypeOfExprType, { TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); }) @@ -1282,6 +1287,7 @@ DEF_TRAVERSE_TYPELOC(DeducedTemplateSpecializationType, { DEF_TRAVERSE_TYPELOC(RecordType, {}) DEF_TRAVERSE_TYPELOC(EnumType, {}) +DEF_TRAVERSE_TYPELOC(InterfaceType, {}) DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {}) DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { TRY_TO(TraverseType(TL.getTypePtr()->getReplacementType())); @@ -1853,6 +1859,16 @@ bool RecursiveASTVisitor::TraverseRecordHelper(RecordDecl *D) { return true; } +template +bool RecursiveASTVisitor::TraverseInterfaceHelper(InterfaceDecl *D) { + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the type, not something that was written in the source. + + TRY_TO(TraverseDeclTemplateParameterLists(D)); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + return true; +} + template bool RecursiveASTVisitor::TraverseCXXBaseSpecifier( const CXXBaseSpecifier &Base) { @@ -1875,6 +1891,7 @@ bool RecursiveASTVisitor::TraverseCXXRecordHelper(CXXRecordDecl *D) { } DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); }) +DEF_TRAVERSE_DECL(InterfaceDecl, { TRY_TO(TraverseInterfaceHelper(D)); }) DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 319d3850346bd4b5016441b1b1f15701e54b5415..1110de1f33fb8a75e71d8b8d6ec59cceff0970dd 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -121,6 +121,7 @@ class ObjCProtocolDecl; class ObjCTypeParamDecl; struct PrintingPolicy; class RecordDecl; +class InterfaceDecl; class Stmt; class TagDecl; class TemplateArgument; @@ -1562,6 +1563,10 @@ protected: unsigned Kind : 8; }; + class ThisTypeBitfields { + friend class ThisType; + }; + /// FunctionTypeBitfields store various bits belonging to FunctionProtoType. /// Only common bits are stored here. Additional uncommon bits are stored /// in a trailing object after FunctionProtoType. @@ -1784,6 +1789,7 @@ protected: AttributedTypeBitfields AttributedTypeBits; AutoTypeBitfields AutoTypeBits; BuiltinTypeBitfields BuiltinTypeBits; + ThisTypeBitfields ThisTypeBits; FunctionTypeBitfields FunctionTypeBits; ObjCObjectTypeBitfields ObjCObjectTypeBits; ReferenceTypeBitfields ReferenceTypeBits; @@ -2475,6 +2481,24 @@ template <> inline const Class##Type *Type::castAs() const { \ } #include "clang/AST/TypeNodes.inc" +class ThisType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + QualType PointeeType; + ThisType(QualType Pointee, QualType CanonType) : + Type(This, CanonType, Pointee->getDependence()), PointeeType(Pointee) {} +public: + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + static bool classof(const Type *T) { return T->getTypeClass() == This; } + QualType getPointeeType() const { return PointeeType; } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) { + ID.AddPointer(Pointee.getAsOpaquePtr()); + } + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getPointeeType()); + } +}; + /// This class is used for builtin types like 'int'. Builtin /// types are always canonical and have a literal name field. class BuiltinType : public Type { @@ -4596,7 +4620,7 @@ public: bool isBeingDefined() const; static bool classof(const Type *T) { - return T->getTypeClass() == Enum || T->getTypeClass() == Record; + return T->getTypeClass() == Enum || T->getTypeClass() == Record || T->getTypeClass() == Interface; } }; @@ -4626,6 +4650,30 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Record; } }; +class InterfaceType : public TagType { +protected: + friend class ASTContext; // ASTContext creates these. + + explicit InterfaceType(const InterfaceDecl *D) + : TagType(Interface, reinterpret_cast(D), QualType()) {} + explicit InterfaceType(TypeClass TC, InterfaceDecl *D) + : TagType(TC, reinterpret_cast(D), QualType()) {} + +public: + InterfaceDecl *getDecl() const { + return reinterpret_cast(TagType::getDecl()); + } + + /// Recursively check all fields in the record for const-ness. If any field + /// is declared const, return true. Otherwise, return false. + bool hasConstFields() const; + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { return T->getTypeClass() == Interface; } +}; + /// A helper class that allows the use of isa/cast/dyncast /// to detect TagType objects of enums. class EnumType : public TagType { @@ -5311,7 +5359,9 @@ enum TagTypeKind { TTK_Class, /// The "enum" keyword. - TTK_Enum + TTK_Enum, + + TTK_Interface_bsc }; /// The elaboration keyword that precedes a qualified type name or @@ -5332,6 +5382,8 @@ enum ElaboratedTypeKeyword { /// The "enum" keyword introduces the elaborated-type-specifier. ETK_Enum, + ETK_Interface_bsc, + /// The "typename" keyword precedes the qualified type name, e.g., /// \c typename T::type. ETK_Typename, diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index 65e95d52c303d44c210a10807138729be0ba71c0..98f48b8b999e12f246569eca46d1f552af0c463f 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -666,6 +666,14 @@ public: } }; +class ThisTypeLoc : public InheritingConcreteTypeLoc{ +public: + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + } +}; + /// Wrapper for source info for typedefs. class TypedefTypeLoc : public InheritingConcreteTypeLocgetDecl(); } }; +class InterfaceTypeLoc : public InheritingConcreteTypeLoc { +public: + InterfaceDecl *getDecl() const { return getTypePtr()->getDecl(); } +}; + /// Wrapper for source info for enum types. class EnumTypeLoc : public InheritingConcreteTypeLoc; } +let Class = ThisType in { + def : Property<"pointeeType", QualType> { + let Read = [{ node->getPointeeType() }]; + } + + def : Creator<[{ return ctx.getThisType(pointeeType); }]>; +} + let Class = ReferenceType in { def : Property<"pointeeTypeAsWritten", QualType> { let Read = [{ node->getPointeeTypeAsWritten() }]; @@ -515,6 +523,17 @@ let Class = RecordType in { }]>; } +let Class = InterfaceType in { + def : Creator<[{ + auto interface = cast(declaration); + QualType result = ctx.getInterfaceType(interface); + if (dependent) + const_cast(result.getTypePtr()) + ->addDependence(TypeDependence::DependentInstantiation); + return result; + }]>; +} + let Class = ElaboratedType in { def : Property<"keyword", ElaboratedTypeKeyword> { let Read = [{ node->getKeyword() }]; diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td index 9f60363e7b92b09337f0ac0444a70a7ab5171f16..0ffb95c891681b020bf67ec32e91374cf35f726f 100644 --- a/clang/include/clang/Basic/DeclNodes.td +++ b/clang/include/clang/Basic/DeclNodes.td @@ -32,6 +32,7 @@ def Named : DeclNode; def ClassTemplateSpecialization : DeclNode; def ClassTemplatePartialSpecialization : DeclNode; + def Interface : DeclNode; def TemplateTypeParm : DeclNode; def Value : DeclNode; def EnumConstant : DeclNode; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 0ed80a481e78d5692f44182939b8fc2b82649d91..81aed6408fb5a9ac9d1866dcaa9d258e8a13d561 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1498,4 +1498,5 @@ def warn_max_tokens_total : Warning< def note_max_tokens_total_override : Note<"total token limit set here">; +def ambiguous_bscmethod_define : Error<"Ambiguous declaration of BSCMethod">; } // end of Parser diagnostics diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b24dac80502f8090809f6597c84c4559d097d1c0..65828b1442f0a3c321427da384b0e28c4fc7b461 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2993,6 +2993,8 @@ def err_attribute_not_clinkage : Error< "function type with %0 attribute must have C linkage">; def err_function_decl_cmse_ns_call : Error< "functions may not be declared with 'cmse_nonsecure_call' attribute">; +def err_interface_member_not_func : Error< + "only function declarations can be interface member !">; def err_attribute_address_function_type : Error< "function type may not be qualified with an address space">; def err_as_qualified_auto_decl : Error< @@ -6454,6 +6456,10 @@ def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">; def err_no_member : Error<"no member named %0 in %1">; def err_no_member_overloaded_arrow : Error< "no member named %0 in %1; did you mean to use '->' instead of '.'?">; +def err_no_member_on_period : Error< + "no instance member named %0 in %1; did you mean to use '::' instead of '.'?">; +def err_no_member_on_arrow : Error< + "no instance member named %0 in %1; did you mean to use '::' instead of '->'?">; def err_member_not_yet_instantiated : Error< "no member %0 in %1; it has not yet been instantiated">; diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index c2736f90b1f5a95864bf382f28aa712286e22b83..3524d8ab5fe124ce46391e51cdefd61af8947286 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -78,6 +78,8 @@ namespace clang { TST_auto_type, // __auto_type extension TST_unknown_anytype, // __unknown_anytype extension TST_atomic, // C11 _Atomic + TST_interface_bsc, + TST_This, #define GENERIC_IMAGE_TYPE(ImgType, Id) TST_##ImgType##_t, // OpenCL image types #include "clang/Basic/OpenCLImageTypes.def" TST_error // erroneous type diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index b6e7b335bfb7934a480ff83215ab894666c60a99..7260f6e2e2451b817cd3248669a569a42ed2d36a 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -328,6 +328,8 @@ KEYWORD(__func__ , KEYALL) KEYWORD(__objc_yes , KEYALL) KEYWORD(__objc_no , KEYALL) +KEYWORD(interface , KEYALL) +KEYWORD(implements , KEYALL) // C++ 2.11p1: Keywords. KEYWORD(asm , KEYCXX|KEYGNU) diff --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td index 011394c3ef455fc6e7a597f37d0c6e858f43c9ad..b98af30c79961c3bdac246e6c569d5f5621f616a 100644 --- a/clang/include/clang/Basic/TypeNodes.td +++ b/clang/include/clang/Basic/TypeNodes.td @@ -87,6 +87,7 @@ def DecltypeType : TypeNode, NeverCanonicalUnlessDependent; def UnaryTransformType : TypeNode, NeverCanonicalUnlessDependent; def TagType : TypeNode; def RecordType : TypeNode, LeafType; +def InterfaceType : TypeNode, LeafType; def EnumType : TypeNode, LeafType; def ElaboratedType : TypeNode, NeverCanonical; def AttributedType : TypeNode, NeverCanonical; @@ -108,4 +109,5 @@ def ObjCObjectPointerType : TypeNode; def PipeType : TypeNode; def AtomicType : TypeNode; def ExtIntType : TypeNode; +def ThisType : TypeNode; def DependentExtIntType : TypeNode, AlwaysDependent; diff --git a/clang/include/clang/Lex/Token.h b/clang/include/clang/Lex/Token.h index 89042a674fec392c0e36419fbc33a6205c6af7e9..d5bb6b01ac0f3481c1c842a5a5d6246447883bd1 100644 --- a/clang/include/clang/Lex/Token.h +++ b/clang/include/clang/Lex/Token.h @@ -67,6 +67,8 @@ class Token { /// Flags - Bits we track about this token, members of the TokenFlags enum. unsigned short Flags; + bool isThis; + public: // Various flags set per token: enum TokenFlags { @@ -174,6 +176,7 @@ public: PtrData = nullptr; UintData = 0; Loc = SourceLocation().getRawEncoding(); + isThis = false; } IdentifierInfo *getIdentifierInfo() const { @@ -247,6 +250,14 @@ public: Flags &= ~Flag; } + void setThis(bool flag) { + isThis = flag; + } + bool getThis() { + return isThis; + } + + /// Return the internal represtation of the flags. /// /// This is only intended for low-level operations such as writing tokens to diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index ad9bb0a6b91fc6d1f11b1c95ac298f56eed142c8..8194a40bc42c23528569ce2ab87cce12e0491241 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1010,6 +1010,9 @@ private: } }; + /// Judge whether there is a \param FindToken before StopTokens. + bool FindUntil(tok::TokenKind FindToken); + /// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the /// input. If so, it is consumed and false is returned. /// @@ -1789,7 +1792,9 @@ private: bool &NotCastExpr, TypeCastState isTypeCast, bool isVectorLiteral = false, - bool *NotPrimaryExpression = nullptr); + bool *NotPrimaryExpression = nullptr, + QualType T = QualType(), + bool HasBSCScopeSpce = false); ExprResult ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand = false, TypeCastState isTypeCast = NotTypeCast, @@ -2356,8 +2361,9 @@ private: const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none, DeclSpecContext DSC = DeclSpecContext::DSC_normal, - LateParsedAttrList *LateAttrs = nullptr, bool BSCMethodFlag = false); + LateParsedAttrList *LateAttrs = nullptr, bool BSCScopeSpecFlag = false); void ParseBSCScopeSpecifiers(DeclSpec &DS); + bool IsBSCMethodAmbiguous(); bool DiagnoseMissingSemiAfterTagDefinition( DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext, LateParsedAttrList *LateAttrs = nullptr); @@ -2372,9 +2378,17 @@ private: void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, DeclSpecContext DSC); + void ParseInterfaceSpecifier(tok::TokenKind TagTokKind, + SourceLocation StartLoc, DeclSpec &DS, + const ParsedTemplateInfo &TemplateInfo, + AccessSpecifier AS, + bool EnteringContext, DeclSpecContext DSC, + ParsedAttributesWithRange &Attributes); void ParseEnumBody(SourceLocation StartLoc, Decl *TagDecl); void ParseStructUnionBody(SourceLocation StartLoc, DeclSpec::TST TagType, RecordDecl *TagDecl); + void ParseInterfaceBody(SourceLocation StartLoc, SourceLocation AttrFixitLoc, + ParsedAttributesWithRange &Attrs, unsigned TagType, Decl *TagDecl); void ParseStructDeclaration( ParsingDeclSpec &DS, @@ -2921,11 +2935,9 @@ private: Declarator &D, SmallVectorImpl &ParamInfo); void ParseParameterDeclarationClause( - DeclaratorContext DeclaratorContext, - ParsedAttributes &attrs, - SmallVectorImpl &ParamInfo, - SourceLocation &EllipsisLoc, - const Type *typePtr = nullptr); + DeclaratorContext DeclaratorContext, ParsedAttributes &attrs, + SmallVectorImpl &ParamInfo, + SourceLocation &EllipsisLoc, const Type *typePtr = nullptr); void ParseBracketDeclarator(Declarator &D); void ParseMisplacedBracketDeclarator(Declarator &D); @@ -3029,6 +3041,9 @@ private: LateParsedAttrList &LateAttrs); void MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(Declarator &D, VirtSpecifiers &VS); +DeclGroupPtrTy ParseInterfaceMemberDeclaration(ParsedAttributes &Attr, +const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), + ParsingDeclRAIIObject *DiagsFromTParams = nullptr); DeclGroupPtrTy ParseCXXClassMemberDeclaration( AccessSpecifier AS, ParsedAttributes &Attr, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), diff --git a/clang/include/clang/Parse/RAIIObjectsForParser.h b/clang/include/clang/Parse/RAIIObjectsForParser.h index e02815bfe54cd04d03496cc8d9931a8ebb93e66d..7f8040d78b90337143160ecfe58f2d9e0c13bb4e 100644 --- a/clang/include/clang/Parse/RAIIObjectsForParser.h +++ b/clang/include/clang/Parse/RAIIObjectsForParser.h @@ -202,23 +202,18 @@ namespace clang { public: BSCScopeSpec(Parser &P) - : DeclSpec(P.getAttrFactory()), - ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {} + : DeclSpec(P.getAttrFactory()), + ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {} BSCScopeSpec(Parser &P, ParsingDeclRAIIObject *RAII) - : DeclSpec(P.getAttrFactory()), - ParsingRAII(P, RAII) {} + : DeclSpec(P.getAttrFactory()), ParsingRAII(P, RAII) {} const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const { return ParsingRAII.getDelayedDiagnosticPool(); } - void complete(Decl *D) { - ParsingRAII.complete(D); - } + void complete(Decl *D) { ParsingRAII.complete(D); } - void abort() { - ParsingRAII.abort(); - } + void abort() { ParsingRAII.abort(); } }; /// A class for parsing a declarator. diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 11c359717ff8d799e7e680e0ea0495da435d5d23..f2dc9c932a5f6c3dccad42f4aa42102a99bf47fc 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -295,6 +295,8 @@ public: static const TST TST_auto_type = clang::TST_auto_type; static const TST TST_unknown_anytype = clang::TST_unknown_anytype; static const TST TST_atomic = clang::TST_atomic; + static const TST TST_interface_bsc = clang::TST_interface_bsc; + static const TST TST_This = clang::TST_This; #define GENERIC_IMAGE_TYPE(ImgType, Id) \ static const TST TST_##ImgType##_t = clang::TST_##ImgType##_t; #include "clang/Basic/OpenCLImageTypes.def" @@ -405,7 +407,7 @@ private: static bool isTypeRep(TST T) { return (T == TST_typename || T == TST_typeofType || - T == TST_underlyingType || T == TST_atomic); + T == TST_underlyingType || T == TST_atomic || T == TST_This); } static bool isExprRep(TST T) { return (T == TST_typeofExpr || T == TST_decltype || T == TST_extint); @@ -420,7 +422,7 @@ public: static bool isDeclRep(TST T) { return (T == TST_enum || T == TST_struct || T == TST_interface || T == TST_union || - T == TST_class); + T == TST_class || T == TST_interface_bsc); } DeclSpec(AttributeFactory &attrFactory) @@ -1824,7 +1826,7 @@ class Declarator { private: const DeclSpec &DS; CXXScopeSpec SS; - DeclSpec *BSCDS=nullptr; + DeclSpec *BSCDS = nullptr; QualType ExtendedType; // BSC only UnqualifiedId Name; @@ -1890,6 +1892,8 @@ private: /// parameters (if any). TemplateParameterList *InventedTemplateParameterList; + bool IsInterfaceMem; + #ifndef _MSC_VER union { #endif @@ -1928,18 +1932,20 @@ public: clear(); } // Used to mark parameters that include 'this'. - bool hasThisParam = false; + bool HasThisParam = false; /// getDeclSpec - Return the declaration-specifier that this declarator was /// declared with. const DeclSpec &getDeclSpec() const { return DS; } - /// getBSCScopeSpec - Return the BSCMethod declaration-specifier that this declarator was - /// declared with. + /// getBSCScopeSpec - Return the BSCMethod declaration-specifier that this + /// declarator was declared with. DeclSpec *getBSCScopeSpec() { return BSCDS; } void setBSCScopeSpec(DeclSpec *ScopeSpec) { BSCDS = ScopeSpec; } QualType getExtendedType() const { return ExtendedType; } - void setExtendedType(QualType ExtendedType) { this->ExtendedType = ExtendedType; } + void setExtendedType(QualType ExtendedType) { + this->ExtendedType = ExtendedType; + } /// getMutableDeclSpec - Return a non-const version of the DeclSpec. This /// should be used with extreme care: declspecs can often be shared between @@ -2230,6 +2236,10 @@ public: Name.setIdentifier(Id, IdLoc); } + bool getIsInterfaceMem() const {return IsInterfaceMem;} + + void setIsInterfaceMem(bool i) {IsInterfaceMem = i;} + /// Set the decomposition bindings for this declarator. void setDecompositionBindings(SourceLocation LSquareLoc, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d9c17632731733b729a8aeb239b52df7c8b32b4f..26e8c4ade9a85c651c64457bf7c320a2778d78f1 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2671,12 +2671,13 @@ public: QualType NewT, QualType OldT); void CheckMain(FunctionDecl *FD, const DeclSpec &D); void CheckMSVCRTEntryPoint(FunctionDecl *FD); - void ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc); + QualType ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc, + bool AddToContextMap); Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition); void CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D); Decl *ActOnParamDeclarator(Scope *S, Declarator &D, int ParamSize = 0, - const Type *typePtr = nullptr); + const Type *TypePtr = nullptr); ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, QualType T); @@ -3002,7 +3003,7 @@ public: Decl *ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth); - FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart, + FieldDecl *HandleField(Scope *S, TagDecl *TagD, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth, InClassInitStyle InitStyle, AccessSpecifier AS); @@ -3015,7 +3016,7 @@ public: FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T, TypeSourceInfo *TInfo, - RecordDecl *Record, SourceLocation Loc, + TagDecl *Record, SourceLocation Loc, bool Mutable, Expr *BitfieldWidth, InClassInitStyle InitStyle, SourceLocation TSSL, @@ -4072,7 +4073,7 @@ public: CXXScopeSpec &SS); bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, bool AllowBuiltinCreation = false, - bool EnteringContext = false); + bool EnteringContext = false, QualType T = QualType()); ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc, RedeclarationKind Redecl = NotForRedeclaration); @@ -5072,7 +5073,8 @@ public: Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand, CorrectionCandidateCallback *CCC = nullptr, - bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr); + bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr, + QualType T = QualType()); void DecomposeUnqualifiedId(const UnqualifiedId &Id, TemplateArgumentListInfo &Buffer, @@ -7076,6 +7078,10 @@ public: /// conditions that are needed for the attribute to have an effect. void checkIllFormedTrivialABIStruct(CXXRecordDecl &RD); + NamedDecl *ActOnInterfaceMemberDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParameterLists); + + void ActOnFinishInterfaceMemberSpecification(Decl *TagDecl); void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac, SourceLocation RBrac, @@ -11313,7 +11319,7 @@ public: bool AllowExplicit = false, bool IsListInitialization = false, bool IsBSCInstanceFunc = false, - CallExpr* Call = nullptr); + CallExpr *Call = nullptr); // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but // will create a runtime trap if the resulting type is not a POD type. diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index 880412cd37258829b9c9a2ebe2341b5cf3339608..8c3fc70d26be46a62b11ef21f262d3ae76839982 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -532,10 +532,10 @@ enum class TemplateSubstitutionKind : char { ClassScopeSpecializationArgs = llvm::None, RewriteKind RK = RewriteKind::None); Decl *VisitBSCMethodDecl(BSCMethodDecl *D, - TemplateParameterList *TemplateParams, - Optional - ClassScopeSpecializationArgs = llvm::None, - RewriteKind RK = RewriteKind::None); + TemplateParameterList *TemplateParams, + Optional + ClassScopeSpecializationArgs = llvm::None, + RewriteKind RK = RewriteKind::None); Decl *VisitFunctionDecl(FunctionDecl *D, TemplateParameterList *TemplateParams, RewriteKind RK = RewriteKind::None); diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index b17f421abccc31fd03660cb0f56d158cc4974379..7d0b21adf04ddba82ec2379f6810e541308b2c10 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1201,6 +1201,8 @@ public: /// The internal '__type_pack_element' template. PREDEF_DECL_TYPE_PACK_ELEMENT_ID = 17, + + PREDEF_TYPE_THIS_ID = 18, }; /// The number of declaration IDs that are predefined. diff --git a/clang/include/clang/Serialization/TypeBitCodes.def b/clang/include/clang/Serialization/TypeBitCodes.def index e92e058106489c6e658b5519d5e888918c72a79f..853ae40297a17ab1de0cb3569f14c371686ef46d 100644 --- a/clang/include/clang/Serialization/TypeBitCodes.def +++ b/clang/include/clang/Serialization/TypeBitCodes.def @@ -62,5 +62,6 @@ TYPE_BIT_CODE(ExtInt, EXT_INT, 50) TYPE_BIT_CODE(DependentExtInt, DEPENDENT_EXT_INT, 51) TYPE_BIT_CODE(ConstantMatrix, CONSTANT_MATRIX, 52) TYPE_BIT_CODE(DependentSizedMatrix, DEPENDENT_SIZE_MATRIX, 53) +TYPE_BIT_CODE(Interface, INTERFACE, 54) #undef TYPE_BIT_CODE diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index cb7f00abf9e91842d6227f283f2f73b83463dee7..393022988b006a1b756b29e01bdb773c8f9d2a66 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1346,6 +1346,8 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, // C++20 (proposed) InitBuiltinType(Char8Ty, BuiltinType::Char8); + if (LangOpts.BSC) + InitBuiltinType(ThisTy, BuiltinType::This); if (LangOpts.CPlusPlus) // C++0x 3.9.1p5, extension for C++ InitBuiltinType(Char16Ty, BuiltinType::Char16); @@ -2232,6 +2234,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = llvm::alignTo(EIT->getNumBits(), Align); break; } + case Type::Interface: case Type::Record: case Type::Enum: { const auto *TT = cast(T); @@ -3176,6 +3179,29 @@ QualType ASTContext::getPointerType(QualType T) const { return QualType(New, 0); } +QualType ASTContext::getThisType(QualType T) const { + llvm::FoldingSetNodeID ID; + ThisType::Profile(ID, T); + + void *InsertPos = nullptr; + if (ThisType *TT = + ThisTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(TT, 0); + QualType Canonical; + if (!T.isCanonical()) { + Canonical = getThisType(getCanonicalType(T)); + + // Get the new insert position for the node we care about. + ThisType *NewIP = + ThisTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; + } + auto *New = new (*this, TypeAlignment) ThisType(T, Canonical); + Types.push_back(New); + ThisTypes.InsertNode(New, InsertPos); + return QualType(New, 0); +} + QualType ASTContext::getAdjustedType(QualType Orig, QualType New) const { llvm::FoldingSetNodeID ID; AdjustedType::Profile(ID, Orig, New); @@ -3459,6 +3485,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { case Type::ObjCObjectPointer: case Type::Record: case Type::Enum: + case Type::Interface: case Type::UnresolvedUsing: case Type::TypeOfExpr: case Type::TypeOf: @@ -4444,7 +4471,10 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const { } else if (const auto *Enum = dyn_cast(Decl)) { assert(Enum->isFirstDecl() && "enum has previous declaration"); return getEnumType(Enum); - } else if (const auto *Using = dyn_cast(Decl)) { + } else if (const auto *Interface = dyn_cast(Decl)) { + assert(Interface->isFirstDecl() && "interface has previous declaration"); + return getInterfaceType(Interface); + }else if (const auto *Using = dyn_cast(Decl)) { Type *newType = new (*this, TypeAlignment) UnresolvedUsingType(Using); Decl->TypeForDecl = newType; Types.push_back(newType); @@ -4483,6 +4513,19 @@ QualType ASTContext::getRecordType(const RecordDecl *Decl) const { return QualType(newType, 0); } +QualType ASTContext::getInterfaceType(const InterfaceDecl *Decl) const { + if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); + + if (const InterfaceDecl *PrevDecl = Decl->getPreviousDecl()) + if (PrevDecl->TypeForDecl) + return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0); + + auto *newType = new (*this, TypeAlignment) InterfaceType(Decl); + Decl->TypeForDecl = newType; + Types.push_back(newType); + return QualType(newType, 0); +} + QualType ASTContext::getEnumType(const EnumDecl *Decl) const { if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); @@ -7495,6 +7538,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S, S += RDecl->isUnion() ? ')' : '}'; return; } + case Type::Interface: + return; case Type::BlockPointer: { const auto *BT = T->castAs(); @@ -9787,6 +9832,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, return mergeFunctionTypes(LHS, RHS, OfBlockPointer, Unqualified); case Type::Record: case Type::Enum: + case Type::Interface: return {}; case Type::Builtin: // Only exactly equal builtin types are compatible, which is tested above. diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 943a8419cbc035cb7114a5412a03111bf0c96e77..465847fe6af19f6e32b0323bd4891ee64b40961c 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -333,6 +333,7 @@ namespace clang { ExpectedType VisitType(const Type *T); ExpectedType VisitAtomicType(const AtomicType *T); ExpectedType VisitBuiltinType(const BuiltinType *T); + ExpectedType VisitThisType(const ThisType *T); ExpectedType VisitDecayedType(const DecayedType *T); ExpectedType VisitComplexType(const ComplexType *T); ExpectedType VisitPointerType(const PointerType *T); @@ -361,6 +362,7 @@ namespace clang { ExpectedType VisitInjectedClassNameType(const InjectedClassNameType *T); // FIXME: DependentDecltypeType ExpectedType VisitRecordType(const RecordType *T); + ExpectedType VisitInterfaceType(const InterfaceType *T); ExpectedType VisitEnumType(const EnumType *T); ExpectedType VisitAttributedType(const AttributedType *T); ExpectedType VisitTemplateTypeParmType(const TemplateTypeParmType *T); @@ -1101,6 +1103,15 @@ ExpectedType ASTNodeImporter::VisitPointerType(const PointerType *T) { return Importer.getToContext().getPointerType(*ToPointeeTypeOrErr); } +ExpectedType ASTNodeImporter::VisitThisType(const ThisType *T) { + // FIXME: Check for blocks support in "to" context. + ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType()); + if (!ToPointeeTypeOrErr) + return ToPointeeTypeOrErr.takeError(); + + return Importer.getToContext().VoidTy; +} + ExpectedType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) { // FIXME: Check for blocks support in "to" context. ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType()); @@ -1402,6 +1413,14 @@ ExpectedType ASTNodeImporter::VisitRecordType(const RecordType *T) { return Importer.getToContext().getTagDeclType(*ToDeclOrErr); } +ExpectedType ASTNodeImporter::VisitInterfaceType(const InterfaceType *T) { + Expected ToDeclOrErr = import(T->getDecl()); + if (!ToDeclOrErr) + return ToDeclOrErr.takeError(); + + return Importer.getToContext().getTagDeclType(*ToDeclOrErr); +} + ExpectedType ASTNodeImporter::VisitEnumType(const EnumType *T) { Expected ToDeclOrErr = import(T->getDecl()); if (!ToDeclOrErr) diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index d004e443ae06a2a65e5d10c23f1229c91561c230..57ff9a4678edebbe43c4038b6b2df466b543463c 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -1018,6 +1018,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case Type::Record: case Type::Enum: + case Type::Interface: if (!IsStructurallyEquivalent(Context, cast(T1)->getDecl(), cast(T2)->getDecl())) return false; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 36c0d620b4732d89c016a3d4534e58fbdb56c377..2de500b8bfe7fcf4eaa61d64911034267d10435a 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1642,7 +1642,12 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS, OS << "(anonymous " << RD->getKindName() << ')'; else OS << *RD; - } else if (const auto *FD = dyn_cast(DC)) { + } else if (const auto *ID = dyn_cast(DC)) { + if (!ID->getIdentifier()) + OS << "(anonymous " << ID->getKindName() << ')'; + else + OS << *ID; + }else if (const auto *FD = dyn_cast(DC)) { const FunctionProtoType *FT = nullptr; if (FD->hasWrittenPrototype()) FT = dyn_cast(FD->getType()->castAs()); @@ -2074,7 +2079,8 @@ static bool isDeclExternC(const T &D) { // language linkage or no language linkage. const DeclContext *DC = D.getDeclContext(); if (DC->isRecord()) { - assert(D.getASTContext().getLangOpts().CPlusPlus || D.getASTContext().getLangOpts().BSC); + assert(D.getASTContext().getLangOpts().CPlusPlus || + D.getASTContext().getLangOpts().BSC); return false; } @@ -3341,7 +3347,7 @@ void FunctionDecl::setParams(ASTContext &C, unsigned FunctionDecl::getMinRequiredArguments() const { if (getASTContext().getLangOpts().BSC) { int num = getNumParams(); - if (num > 0 && parameters()[0] && parameters()[0]->isThisParam) { + if (num > 0 && parameters()[0] && parameters()[0]->IsThisParam) { num--; } return num; @@ -4508,6 +4514,40 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, return R; } +InterfaceDecl::InterfaceDecl(Kind DK, TagKind TK, const ASTContext &C, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + InterfaceDecl *PrevDecl) + : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) { + assert(classof(static_cast(this)) && "Invalid Kind!"); + setHasFlexibleArrayMember(false); + setAnonymousStructOrUnion(false); + setHasObjectMember(false); + setHasVolatileMember(false); + setHasLoadedFieldsFromExternalStorage(false); + setNonTrivialToPrimitiveDefaultInitialize(false); + setNonTrivialToPrimitiveCopy(false); + setNonTrivialToPrimitiveDestroy(false); + setHasNonTrivialToPrimitiveDefaultInitializeCUnion(false); + setHasNonTrivialToPrimitiveDestructCUnion(false); + setHasNonTrivialToPrimitiveCopyCUnion(false); + setParamDestroyedInCallee(false); + setArgPassingRestrictions(APK_CanPassInRegs); +} + +InterfaceDecl *InterfaceDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, InterfaceDecl* PrevDecl) { + InterfaceDecl *R = new (C, DC) InterfaceDecl(Interface, TK, C, DC, + StartLoc, IdLoc, Id, PrevDecl); + R->setMayHaveOutOfDateDef(C.getLangOpts().Modules); + + C.getTypeDeclType(R, PrevDecl); + return R; +} + + + RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { RecordDecl *R = new (C, ID) RecordDecl(Record, TTK_Struct, C, nullptr, SourceLocation(), @@ -4521,20 +4561,37 @@ bool RecordDecl::isInjectedClassName() const { cast(getDeclContext())->getDeclName() == getDeclName(); } +bool InterfaceDecl::isInjectedClassName() const { + return isImplicit() && getDeclName() && getDeclContext()->isInterface() && + cast(getDeclContext())->getDeclName() == getDeclName(); +} + bool RecordDecl::isLambda() const { if (auto RD = dyn_cast(this)) return RD->isLambda(); return false; } +bool InterfaceDecl::isLambda() const { + return false; +} + bool RecordDecl::isCapturedRecord() const { return hasAttr(); } +bool InterfaceDecl::isCapturedRecord() const { + return hasAttr(); +} + void RecordDecl::setCapturedRecord() { addAttr(CapturedRecordAttr::CreateImplicit(getASTContext())); } +void InterfaceDecl::setCapturedRecord() { + addAttr(CapturedRecordAttr::CreateImplicit(getASTContext())); +} + bool RecordDecl::isOrContainsUnion() const { if (isUnion()) return true; @@ -4550,6 +4607,10 @@ bool RecordDecl::isOrContainsUnion() const { return false; } +bool InterfaceDecl::isOrContainsUnion() const { + return false; +} + RecordDecl::field_iterator RecordDecl::field_begin() const { if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage()) LoadFieldsFromExternalStorage(); @@ -4557,6 +4618,13 @@ RecordDecl::field_iterator RecordDecl::field_begin() const { return field_iterator(decl_iterator(FirstDecl)); } +RecordDecl::field_iterator InterfaceDecl::field_begin() const { + if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage()) + LoadFieldsFromExternalStorage(); + + return field_iterator(decl_iterator(FirstDecl)); +} + /// completeDefinition - Notes that the definition of this type is now /// complete. void RecordDecl::completeDefinition() { @@ -4564,6 +4632,11 @@ void RecordDecl::completeDefinition() { TagDecl::completeDefinition(); } +void InterfaceDecl::completeDefinition() { + assert(!isCompleteDefinition() && "Cannot redefine interface!"); + TagDecl::completeDefinition(); +} + /// isMsStruct - Get whether or not this record uses ms_struct layout. /// This which can be turned on with an attribute, pragma, or the /// -mms-bitfields command-line option. @@ -4571,6 +4644,10 @@ bool RecordDecl::isMsStruct(const ASTContext &C) const { return hasAttr() || C.getLangOpts().MSBitfields == 1; } +bool InterfaceDecl::isMsStruct(const ASTContext &C) const { + return hasAttr() || C.getLangOpts().MSBitfields == 1; +} + void RecordDecl::LoadFieldsFromExternalStorage() const { ExternalASTSource *Source = getASTContext().getExternalSource(); assert(hasExternalLexicalStorage() && Source && "No external storage?"); @@ -4597,6 +4674,32 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { /*FieldsAlreadyLoaded=*/false); } +void InterfaceDecl::LoadFieldsFromExternalStorage() const { + ExternalASTSource *Source = getASTContext().getExternalSource(); + assert(hasExternalLexicalStorage() && Source && "No external storage?"); + + // Notify that we have a RecordDecl doing some initialization. + ExternalASTSource::Deserializing TheFields(Source); + + SmallVector Decls; + setHasLoadedFieldsFromExternalStorage(true); + Source->FindExternalLexicalDecls(this, [](Decl::Kind K) { + return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K); + }, Decls); + +#ifndef NDEBUG + // Check that all decls we got were FieldDecls. + for (unsigned i=0, e=Decls.size(); i != e; ++i) + assert(isa(Decls[i]) || isa(Decls[i])); +#endif + + if (Decls.empty()) + return; + + std::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls, + /*FieldsAlreadyLoaded=*/false); +} + bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const { ASTContext &Context = getASTContext(); const SanitizerMask EnabledAsanMask = Context.getLangOpts().Sanitize.Mask & @@ -4642,6 +4745,10 @@ bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const { return ReasonToReject < 0; } +bool InterfaceDecl::mayInsertExtraPadding(bool EmitRemark) const { + return false; +} + const FieldDecl *RecordDecl::findFirstNamedDataMember() const { for (const auto *I : fields()) { if (I->getIdentifier()) @@ -4657,6 +4764,21 @@ const FieldDecl *RecordDecl::findFirstNamedDataMember() const { return nullptr; } +const FieldDecl *InterfaceDecl::findFirstNamedDataMember() const { + for (const auto *I : fields()) { + if (I->getIdentifier()) + return I; + + if (const auto *RT = I->getType()->getAs()) + if (const FieldDecl *NamedDataMember = + RT->getDecl()->findFirstNamedDataMember()) + return NamedDataMember; + } + + // We didn't find a named data member. + return nullptr; +} + //===----------------------------------------------------------------------===// // BlockDecl Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 3e9d1d032b743257753bbe5b6ab289a0c7787e73..ebcc98b8325111c158311c3cd520d77b7928f257 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -798,6 +798,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Record: case CXXRecord: case Enum: + case Interface: return IDNS_Tag | IDNS_Type; case Namespace: diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 1386504b436d323f9b24d918f21e528823bad827..dd285c8ba85db6d6bc8f29a61e3c84e84f1e792f 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -143,6 +143,8 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, return R; } + + CXXRecordDecl * CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, SourceLocation Loc, @@ -2190,18 +2192,14 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD, return FinalOverriders.size() == 1 ? FinalOverriders.front() : nullptr; } -BSCMethodDecl *BSCMethodDecl::Create(ASTContext &C, DeclContext *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - StorageClass SC, bool isInline, - ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, - Expr *TrailingRequiresClause) { - return new (C, RD) - BSCMethodDecl(BSCMethod, C, RD, StartLoc, NameInfo, T, TInfo, SC, - isInline, ConstexprKind, EndLocation, - TrailingRequiresClause); +BSCMethodDecl *BSCMethodDecl::Create( + ASTContext &C, DeclContext *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + StorageClass SC, bool isInline, ConstexprSpecKind ConstexprKind, + SourceLocation EndLocation, Expr *TrailingRequiresClause) { + return new (C, RD) BSCMethodDecl(BSCMethod, C, RD, StartLoc, NameInfo, T, + TInfo, SC, isInline, ConstexprKind, + EndLocation, TrailingRequiresClause); } BSCMethodDecl *BSCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 4b3258be0989450f67727c500378b1c42d9ed6ba..003fca25e245a088af920e9dbe382e796372f891 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -11005,6 +11005,8 @@ EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) { case Type::Complex: return GCCTypeClass::Complex; + case Type::Interface: + return GCCTypeClass::ClassOrStruct; case Type::Record: return CanTy->isUnionType() ? GCCTypeClass::Union : GCCTypeClass::ClassOrStruct; diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 5cad84a96845b10a019973e6d161fa065ecc9d2d..e362508d228b8e0bdae8e5ead56838b9560bdabf 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2151,6 +2151,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::Enum: case Type::Record: + case Type::Interface: mangleSourceNameWithAbiTags(cast(Ty)->getDecl()); break; @@ -3113,6 +3114,11 @@ void CXXNameMangler::mangleType(const EnumType *T) { void CXXNameMangler::mangleType(const RecordType *T) { mangleType(static_cast(T)); } + +void CXXNameMangler::mangleType(const InterfaceType *T) { + mangleType(static_cast(T)); +} + void CXXNameMangler::mangleType(const TagType *T) { mangleName(T->getDecl()); } @@ -3215,6 +3221,10 @@ void CXXNameMangler::mangleType(const ComplexType *T) { mangleType(T->getElementType()); } +void CXXNameMangler::mangleType(const ThisType *T) { + return; +} + // ARM's ABI for Neon vector types specifies that they should be mangled as // if they are structs (to match ARM's initial implementation). The // vector type must be one of the special types predefined by ARM. @@ -3648,6 +3658,7 @@ void CXXNameMangler::mangleType(const DependentNameType *T) { case ETK_Struct: case ETK_Class: case ETK_Interface: + case ETK_Interface_bsc: Out << "Ts"; break; case ETK_Union: diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp index 3282fcbd584f3f30809e62fdd723f05af458236d..3e4a497aef988727f8f87e140d27b52f0a984a8b 100644 --- a/clang/lib/AST/Mangle.cpp +++ b/clang/lib/AST/Mangle.cpp @@ -107,6 +107,10 @@ static CCMangling getCallingConvMangling(const ASTContext &Context, bool MangleContext::shouldMangleDeclName(const NamedDecl *D) { const ASTContext &ASTContext = getASTContext(); + const auto *MD = dyn_cast(D); + if (MD && !MD->getExtendedType().isNull()) + return true; + CCMangling CC = getCallingConvMangling(ASTContext, D); if (CC != CCM_Other) return true; @@ -171,6 +175,14 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) { return; } + const auto *MD = dyn_cast(D); + if (MD && !MD->getExtendedType().isNull()) { + Out << "_ZN"; + mangleTypeName(MD->getExtendedType(), Out); + Out << D->getIdentifier()->getName(); + return; + } + bool MCXX = shouldMangleCXXName(D); const TargetInfo &TI = Context.getTargetInfo(); if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) { diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index df6c566abc7d789842e829e07d110898717bac70..a04f5c5b45309cb8fd9d50a7121c310228b08601 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -2744,6 +2744,7 @@ void MicrosoftCXXNameMangler::mangleTagTypeKind(TagTypeKind TTK) { break; case TTK_Struct: case TTK_Interface: + case TTK_Interface_bsc: Out << 'U'; break; case TTK_Class: @@ -2762,6 +2763,10 @@ void MicrosoftCXXNameMangler::mangleType(const RecordType *T, Qualifiers, SourceRange) { mangleType(cast(T)->getDecl()); } +void MicrosoftCXXNameMangler::mangleType(const InterfaceType *T, Qualifiers, + SourceRange) { + mangleType(cast(T)->getDecl()); +} void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) { mangleTagTypeKind(TD->getTagKind()); mangleName(TD); @@ -2938,6 +2943,11 @@ void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T, mangleType(PointeeType, Range); } +void MicrosoftCXXNameMangler::mangleType(const ThisType *T, + Qualifiers Quals, SourceRange Range) { + return; +} + // ::= // ::= $$Q E? // # the E is required for 64-bit non-static rvalue references diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 9a8e84c4fde6af4e2f10d78b6c100676639f991b..381cbda1a14a5e0c616e0b8c99c3d14d1c82a68c 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -841,6 +841,10 @@ public: VisitType(T); } + void VisitThisType(const ThisType *T) { + VisitType(T); + } + void VisitComplexType(const ComplexType *T) { AddQualType(T->getElementType()); VisitType(T); @@ -1018,6 +1022,7 @@ public: void VisitRecordType(const RecordType *T) { VisitTagType(T); } void VisitEnumType(const EnumType *T) { VisitTagType(T); } + void VisitInterfaceType(const InterfaceType *T) { VisitTagType(T); } void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { ID.AddInteger(T->getNumArgs()); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 034e175f1352499bf1d1131d86a054a8b217b5cd..31b98653cfba89577ff06d1217e7daac45e25f8b 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2795,6 +2795,7 @@ TypeWithKeyword::getKeywordForTypeSpec(unsigned TypeSpec) { case TST_interface: return ETK_Interface; case TST_union: return ETK_Union; case TST_enum: return ETK_Enum; + case TST_interface_bsc: return ETK_Interface_bsc; } } @@ -2806,6 +2807,7 @@ TypeWithKeyword::getTagTypeKindForTypeSpec(unsigned TypeSpec) { case TST_interface: return TTK_Interface; case TST_union: return TTK_Union; case TST_enum: return TTK_Enum; + case TST_interface_bsc: return TTK_Interface_bsc; } llvm_unreachable("Type specifier is not a tag type kind."); @@ -2819,6 +2821,7 @@ TypeWithKeyword::getKeywordForTagTypeKind(TagTypeKind Kind) { case TTK_Interface: return ETK_Interface; case TTK_Union: return ETK_Union; case TTK_Enum: return ETK_Enum; + case TTK_Interface_bsc: return ETK_Interface_bsc; } llvm_unreachable("Unknown tag type kind."); } @@ -2831,6 +2834,7 @@ TypeWithKeyword::getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword) { case ETK_Interface: return TTK_Interface; case ETK_Union: return TTK_Union; case ETK_Enum: return TTK_Enum; + case ETK_Interface_bsc: return TTK_Interface_bsc; case ETK_None: // Fall through. case ETK_Typename: llvm_unreachable("Elaborated type keyword is not a tag type kind."); @@ -2847,6 +2851,7 @@ TypeWithKeyword::KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword) { case ETK_Class: case ETK_Struct: case ETK_Interface: + case ETK_Interface_bsc: case ETK_Union: case ETK_Enum: return true; @@ -2863,6 +2868,7 @@ StringRef TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) { case ETK_Interface: return "__interface"; case ETK_Union: return "union"; case ETK_Enum: return "enum"; + case ETK_Interface_bsc: return "interface"; } llvm_unreachable("Unknown elaborated type keyword."); @@ -3836,7 +3842,8 @@ static CachedProperties computeCachedProperties(const Type *T) { return CachedProperties(ExternalLinkage, false); case Type::Record: - case Type::Enum: { + case Type::Enum: + case Type::Interface:{ const TagDecl *Tag = cast(T)->getDecl(); // C++ [basic.link]p8: @@ -3938,6 +3945,7 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) { case Type::Record: case Type::Enum: + case Type::Interface: return getDeclLinkageAndVisibility(cast(T)->getDecl()); case Type::Complex: @@ -4138,6 +4146,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::FunctionProto: case Type::FunctionNoProto: case Type::Record: + case Type::Interface: case Type::DeducedTemplateSpecialization: case Type::Enum: case Type::InjectedClassName: diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 25d7874b53fb594a2a45ba4c2b5c17d3237574f7..80c96507f3400e4eb41687794fca2825427eac0c 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -218,6 +218,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::UnaryTransform: case Type::Record: case Type::Enum: + case Type::Interface: case Type::Elaborated: case Type::TemplateTypeParm: case Type::SubstTemplateTypeParmPack: @@ -375,6 +376,13 @@ void TypePrinter::printComplexAfter(const ComplexType *T, raw_ostream &OS) { printAfter(T->getElementType(), OS); } +void TypePrinter::printThisBefore(const ThisType *T, raw_ostream &OS) { + OS << "This "; +} + +void TypePrinter::printThisAfter(const ThisType *T, raw_ostream &OS) { +} + void TypePrinter::printPointerBefore(const PointerType *T, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false); @@ -1381,6 +1389,12 @@ void TypePrinter::printEnumBefore(const EnumType *T, raw_ostream &OS) { void TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) {} +void TypePrinter::printInterfaceBefore(const InterfaceType *T, raw_ostream &OS) { + printTag(T->getDecl(), OS); +} + +void TypePrinter::printInterfaceAfter(const InterfaceType *T, raw_ostream &OS) {} + void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T, raw_ostream &OS) { TemplateTypeParmDecl *D = T->getDecl(); diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 0e8a9a289a38fad4b1126e6ce62487eab8f7174d..db6e32b0f2725461693394c7f1e0e08c1073f01b 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -102,6 +102,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::Binding: llvm_unreachable("Declaration should not be in declstmts!"); case Decl::Record: // struct/union/class X; + case Decl::Interface: case Decl::CXXRecord: // struct/union/class X; [C++] if (CGDebugInfo *DI = getDebugInfo()) if (cast(D).getDefinition()) diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index b393c88f775117f42b62a7b608136242bdb8afd4..77261b3552c6e1ce4718a19c54f6661d3a6e2d06 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -265,6 +265,7 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) { case Type::IncompleteArray: case Type::VariableArray: case Type::Record: + case Type::Interface: case Type::ObjCObject: case Type::ObjCInterface: return TEK_Aggregate; @@ -2126,6 +2127,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { case Type::ConstantMatrix: case Type::Record: case Type::Enum: + case Type::Interface: case Type::Elaborated: case Type::TemplateSpecialization: case Type::ObjCTypeParam: diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 7537ac12f1c8115caebb0268cdf05b92a39e6d34..2173caf96d58e616e918c887bdf3a3f9a072318e 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -425,6 +425,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { llvm::Type *ResultType = nullptr; switch (Ty->getTypeClass()) { case Type::Record: // Handled above. + case Type::Interface: #define TYPE(Class, Base) #define ABSTRACT_TYPE(Class, Base) #define NON_CANONICAL_TYPE(Class, Base) case Type::Class: diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 50fb30a95cbbfe58c91266f7c3b02bc8362d978b..e8d3bc080051e3d8ea687c412d9644e44f32015e 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3424,6 +3424,7 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) { VTableName = "_ZTVN10__cxxabiv120__function_type_infoE"; break; + case Type::Interface: case Type::Enum: // abi::__enum_type_info. VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE"; @@ -3687,6 +3688,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( // abi::__function_type_info adds no data members to std::type_info. break; + case Type::Interface: case Type::Enum: // Itanium C++ ABI 2.9.5p5: // abi::__enum_type_info adds no data members to std::type_info. diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 03f75ca2d0e249e3c8c7f397abc5ffbb6534d30a..8d4235cc2ec25b0bf2de19beb43446bb49173d42 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2125,7 +2125,7 @@ static bool IsInputCompatibleWithStandard(InputKind IK, return S.getLanguage() == Language::CXX || S.getLanguage() == Language::HIP; case Language::BSC: - return S.getLanguage() == Language::BSC; + return S.getLanguage() == Language::C || S.getLanguage() == Language::BSC; case Language::Asm: // Accept (and ignore) all -std= values. diff --git a/clang/lib/Index/IndexSymbol.cpp b/clang/lib/Index/IndexSymbol.cpp index 0d2e557cdd3672c5ddde46b4a91e8e105044e7f1..88c66c5ac9c83582e14f795b11e3e3aa59474e44 100644 --- a/clang/lib/Index/IndexSymbol.cpp +++ b/clang/lib/Index/IndexSymbol.cpp @@ -106,6 +106,8 @@ SymbolInfo index::getSymbolInfo(const Decl *D) { if (const TagDecl *TD = dyn_cast(D)) { switch (TD->getTagKind()) { + //TODO: make interface symbolkind + case TTK_Interface_bsc: case TTK_Struct: Info.Kind = SymbolKind::Struct; break; case TTK_Union: diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp index abaeb1a4232f292184fed04867bb52607b4e8eb9..068f5c382bf06afb95d416a3f2068e211079231b 100644 --- a/clang/lib/Index/USRGeneration.cpp +++ b/clang/lib/Index/USRGeneration.cpp @@ -510,6 +510,7 @@ void USRGenerator::VisitTagDecl(const TagDecl *D) { switch (D->getTagKind()) { case TTK_Interface: + case TTK_Interface_bsc: case TTK_Class: case TTK_Struct: Out << "@ST"; break; case TTK_Union: Out << "@UT"; break; @@ -522,6 +523,7 @@ void USRGenerator::VisitTagDecl(const TagDecl *D) { switch (D->getTagKind()) { case TTK_Interface: + case TTK_Interface_bsc: case TTK_Class: case TTK_Struct: Out << "@SP"; break; case TTK_Union: Out << "@UP"; break; @@ -534,6 +536,7 @@ void USRGenerator::VisitTagDecl(const TagDecl *D) { if (!AlreadyStarted) { switch (D->getTagKind()) { case TTK_Interface: + case TTK_Interface_bsc: case TTK_Class: case TTK_Struct: Out << "@S"; break; case TTK_Union: Out << "@U"; break; diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 431e446c1f200c6813c548fd86a89c6d3b2475ef..d1fa83e4e954acfeb1c5b0e95afd307cb9bbee87 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -1642,6 +1642,10 @@ bool Lexer::tryConsumeIdentifierUTF8Char(const char *&CurPtr) { bool Lexer::LexIdentifier(Token &Result, const char *CurPtr) { // Match [_A-Za-z0-9]*, we have already matched [_A-Za-z$] unsigned Size; + Size = 1; + if (*(CurPtr-1) == 'T' && *CurPtr == 'h' && *(CurPtr+1) == 'i' && *(CurPtr+2) == 's'){ + Result.setThis(true); + } unsigned char C = *CurPtr++; while (isIdentifierBody(C)) C = *CurPtr++; @@ -3225,7 +3229,6 @@ LexNextToken: } unsigned SizeTmp, SizeTmp2; // Temporaries for use in cases below. - // Read a character, advancing over it. char Char = getAndAdvanceChar(CurPtr, Result); tok::TokenKind Kind; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 20b40259a8c8a59a1a947ebc41d0b5602c7d5bbc..136fdf420c4151128761cb1fccbc96cca7e8cd3c 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1566,7 +1566,6 @@ void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs, SourceLocation CorrectLocation) { assert((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) || Tok.is(tok::kw_alignas)); - // Consume the attributes. SourceLocation Loc = Tok.getLocation(); ParseCXX11Attributes(Attrs); @@ -1977,10 +1976,10 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, &LateParsedAttrs); if (!D.getExtendedType().isNull()) { if (auto *MD = dyn_cast(TheDecl)) { - MD->setExtendedType(D.getExtendedType()); - MD->setHasThisParam(D.hasThisParam); + MD->setExtendedType(D.getExtendedType()); + MD->setHasThisParam(D.HasThisParam); } - } + } return Actions.ConvertDeclToDeclGroup(TheDecl); } @@ -2043,15 +2042,17 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, SmallVector DeclsInGroup; Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes( D, ParsedTemplateInfo(), FRI); - + if (LateParsedAttrs.size() > 0) ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false); D.complete(FirstDecl); if (FirstDecl) { - if (auto FD = dyn_cast(FirstDecl)) - FD->setHasThisParam(D.hasThisParam); + if (auto FD = dyn_cast(FirstDecl)) { + FD->setHasThisParam(D.HasThisParam); + FD->setExtendedType(D.getExtendedType()); + } DeclsInGroup.push_back(FirstDecl); - } + } bool ExpectSemi = Context != DeclaratorContext::ForInit; @@ -2597,6 +2598,9 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, TagKind=tok::kw___interface;break; case DeclSpec::TST_class: TagName="class" ; FixitTagName = "class " ;TagKind=tok::kw_class ;break; + case DeclSpec::TST_interface_bsc: + TagName="interface"; FixitTagName = "interface "; + TagKind=tok::kw_interface;break; } if (TagName) { @@ -2965,10 +2969,10 @@ static void SetupFixedPointError(const LangOptions &LangOpts, } void Parser::ParseBSCScopeSpecifiers(DeclSpec &DS) { - bool BSCMethodFlag = true; + bool BSCScopeSpecFlag = true; ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, - DeclSpecContext::DSC_normal, nullptr, - BSCMethodFlag); + DeclSpecContext::DSC_normal, nullptr, + BSCScopeSpecFlag); } /// ParseDeclarationSpecifiers @@ -3003,7 +3007,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext, LateParsedAttrList *LateAttrs, - bool BSCMethodFlag) { + bool BSCScopeSpecFlag) { + bool BSCMethodFlag = false; + if (getLangOpts().BSC && !BSCScopeSpecFlag) + BSCMethodFlag = FindUntil(tok::coloncolon); if (DS.getSourceRange().isInvalid()) { // Start the range at the current token but make the end of the range // invalid. This will make the entire range invalid unless we successfully @@ -3019,15 +3026,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // We use Sema's policy to get bool macros right. PrintingPolicy Policy = Actions.getPrintingPolicy(); while (1) { - if (getLangOpts().BSC && DS.hasTypeSpecifier() && - ((BSCMethodFlag && Tok.is(tok::coloncolon) && - NextToken().is(tok::identifier)) || - (NextToken().is(tok::coloncolon) || - GetLookAheadToken(2).is(tok::coloncolon)))) { - ProhibitAttributes(attrs); - DS.Finish(Actions, Policy); - return; - } bool isInvalid = false; bool isStorageClass = false; const char *PrevSpec = nullptr; @@ -3051,6 +3049,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, SourceLocation Loc = Tok.getLocation(); + if (BSCMethodFlag) { + if (DS.hasTypeSpecifier()) + goto DoneWithDeclSpec; + // if the method is unsinged long long::getA(){...}, which causes a + // misunderstanding on whether the BSCScopeSpec is long long or long, it + // throws out an error. + if (IsBSCMethodAmbiguous()) + Diag(Loc, diag::ambiguous_bscmethod_define); + } + switch (Tok.getKind()) { default: DoneWithDeclSpec: @@ -3121,6 +3129,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::coloncolon: // ::foo::bar // C++ scope specifier. Annotate and loop, or bail out on error. + if (BSCScopeSpecFlag) + goto DoneWithDeclSpec; if (TryAnnotateCXXScopeToken(EnteringContext)) { if (!DS.hasTypeSpecifier()) DS.SetTypeSpecError(); @@ -3301,6 +3311,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___super: case tok::kw_decltype: case tok::identifier: { + if (Tok.getThis()) { + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_This, Loc, PrevSpec, + DiagID, Policy); + break; + } // This identifier can only be a typedef name if we haven't already seen // a type-specifier. Without this check we misparse: // typedef int X; struct Y { short X; }; as 'short int'. @@ -3972,6 +3987,17 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSContext); continue; + case tok::kw_interface: { + ConsumeToken(); + ParsedAttributesWithRange Attributes(AttrFactory); + ParseInterfaceSpecifier(tok::kw_interface, Loc, DS, TemplateInfo, AS, + EnteringContext, DSContext, Attributes); + if (!Attributes.empty()) { + AttrsLastTime = true; + attrs.takeAllFrom(Attributes); + } + continue;} + // cv-qualifier: case tok::kw_const: isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID, @@ -4070,6 +4096,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ParseOpenCLQualifiers(DS.getAttributes()); break; + case tok::less: // GCC ObjC supports types like "" as a synonym for // "id". This is hopelessly old fashioned and dangerous, @@ -4355,6 +4382,130 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); } +Parser::DeclGroupPtrTy Parser::ParseInterfaceMemberDeclaration(ParsedAttributes &AccessAttrs, const ParsedTemplateInfo &TemplateInfo, +ParsingDeclRAIIObject *TemplateDiags) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + ParsedAttributesWithRange attrs(AttrFactory); + ParsedAttributesViewWithRange FnAttrs; + // we need to keep these attributes for future diagnostic + // before they are taken over by declaration specifier + FnAttrs.addAll(attrs.begin(), attrs.end()); + FnAttrs.Range = attrs.Range; + LateParsedAttrList CommonLateParsedAttrs; + // decl-specifier-seq: + // Parse the common declaration-specifiers piece + ParsingDeclSpec DS(*this, TemplateDiags); + DS.takeAttributesFrom(attrs); + ParseDeclarationSpecifiers(DS, TemplateInfo, AS_public, DeclSpecContext::DSC_class, &CommonLateParsedAttrs); + MultiTemplateParamsArg TemplateParams(TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : nullptr, + TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); + + if (TryConsumeToken(tok::semi)) { + RecordDecl *AnonRecord = nullptr; + Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_public, DS, TemplateParams, false, AnonRecord); + DS.complete(TheDecl); + if (AnonRecord) { + Decl* decls[] = {AnonRecord, TheDecl}; + return Actions.BuildDeclaratorGroup(decls); + } + return Actions.ConvertDeclToDeclGroup(TheDecl); + } + ParsingDeclarator DeclaratorInfo(*this, DS, DeclaratorContext::Member); + if (TemplateInfo.TemplateParams) + DeclaratorInfo.setTemplateParameterLists(TemplateParams); + VirtSpecifiers VS; + //Hold late-parsed attributes so we can attach a Decl to them later. + LateParsedAttrList LateParsedAttrs; + SmallVector DeclsInGroup; + ExprResult BitfieldSize; + ExprResult TrailingRequiresClause; + ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs); + while(1) { + NamedDecl *ThisDecl = Actions.ActOnInterfaceMemberDeclarator( + getCurScope(), DeclaratorInfo, TemplateParams); + if (ThisDecl) { + Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs); + if (!ThisDecl->isInvalidDecl()) { + //Set the Decl for any late parsed attributes + for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) + CommonLateParsedAttrs[i]->addDecl(ThisDecl); + for (unsigned i = 0, ni = LateParsedAttrs.size(); i< ni; ++i) + LateParsedAttrs[i]->addDecl(ThisDecl); + } + Actions.FinalizeDeclaration(ThisDecl); + DeclsInGroup.push_back(ThisDecl); //Put each Decl inside struct Foo + if (DeclaratorInfo.isFunctionDeclarator() && + DeclaratorInfo.getDeclSpec().getStorageClassSpec() != + DeclSpec::SCS_typedef) + HandleMemberFunctionDeclDelays(DeclaratorInfo, ThisDecl); + } + LateParsedAttrs.clear(); + DeclaratorInfo.complete(ThisDecl); + // if we dont have a comma, it is either the end of the list (a, ';') + // or an error, bail out + SourceLocation CommaLoc; + if (!TryConsumeToken(tok::comma, CommaLoc)) + break; + if (Tok.isAtStartOfLine() && + !MightBeDeclarator(DeclaratorContext::Member)) { + Diag(CommaLoc, diag::err_expected_semi_declaration) << FixItHint::CreateReplacement(CommaLoc, ";"); + break; + } + // Parse the next declarator + DeclaratorInfo.clear(); + VS.clear(); + BitfieldSize = ExprResult(false); + DeclaratorInfo.setCommaLoc(CommaLoc); + if (ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) + break; + } + return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup); +} + + + +void Parser::ParseInterfaceBody(SourceLocation RecordLoc, SourceLocation AttrFixitLoc, + ParsedAttributesWithRange &Attrs, + unsigned TagType, Decl *TagDecl) { + PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc, + "parsing interface body"); + bool NonNestedClass = true; + // Enter a scope for the class + ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope); + + // Note that we are parsing a new (potentially-nested) class definition + ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass, false); + if (TagDecl) + Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); + if (!Tok.is(tok::l_brace)) { + if (TagDecl) + Actions.ActOnTagDefinitionError(getCurScope(), TagDecl); + return; + } + BalancedDelimiterTracker T(*this, tok::l_brace); + T.consumeOpen(); + ParsedAttributesWithRange AccessAttrs(AttrFactory); + if (TagDecl) { + // While we still have something to read. read the member-decls + while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { + // Each iter of this loop reads one member-declaration + ParseInterfaceMemberDeclaration(AccessAttrs); + MaybeDestroyTemplateIds(); + } + T.consumeClose(); + } else { + SkipUntil(tok::r_brace); + } + ParsedAttributes attrs(AttrFactory); + if (TagDecl) { + Actions.ActOnFinishInterfaceMemberSpecification(TagDecl);} + if (TagDecl) { + Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); + } + // Leave the class scope + ParsingDef.Pop(); + ClassScope.Exit(); + } /// ParseEnumSpecifier /// enum-specifier: [C99 6.7.2.2] /// 'enum' identifier[opt] '{' enumerator-list '}' @@ -4760,6 +4911,572 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, Diag(StartLoc, DiagID) << PrevSpec; } +void Parser::ParseInterfaceSpecifier(tok::TokenKind TagTokKind, + SourceLocation StartLoc, DeclSpec &DS, + const ParsedTemplateInfo &TemplateInfo, + AccessSpecifier AS, + bool EnteringContext, DeclSpecContext DSC, + ParsedAttributesWithRange &Attributes) { + assert(TagTokKind == tok::kw_interface && "Not a class specifier"); + DeclSpec::TST TagType = DeclSpec::TST_interface_bsc; + if (Tok.is(tok::code_completion)) { + // Code completion for a struct, class, or union name. + Actions.CodeCompleteTag(getCurScope(), TagType); + return cutOffParsing(); + } + + // C++03 [temp.explicit] 14.7.2/8: + // The usual access checking rules do not apply to names used to specify + // explicit instantiations. + // + // As an extension we do not perform access checking on the names used to + // specify explicit specializations either. This is important to allow + // specializing traits classes for private types. + // + // Note that we don't suppress if this turns out to be an elaborated + // type specifier. + bool shouldDelayDiagsInTag = + (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation || + TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization); + SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag); + + ParsedAttributesWithRange attrs(AttrFactory); + // If attributes exist after tag, parse them. + MaybeParseGNUAttributes(attrs); + MaybeParseMicrosoftDeclSpecs(attrs); + + // Parse inheritance specifiers. + if (Tok.isOneOf(tok::kw___single_inheritance, + tok::kw___multiple_inheritance, + tok::kw___virtual_inheritance)) + ParseMicrosoftInheritanceClassAttributes(attrs); + + // If C++0x attributes exist here, parse them. + // FIXME: Are we consistent with the ordering of parsing of different + // styles of attributes? + MaybeParseCXX11Attributes(attrs); + + // Source location used by FIXIT to insert misplaced + // C++11 attributes + SourceLocation AttrFixitLoc = Tok.getLocation(); + + struct PreserveAtomicIdentifierInfoRAII { + PreserveAtomicIdentifierInfoRAII(Token &Tok, bool Enabled) + : AtomicII(nullptr) { + if (!Enabled) + return; + assert(Tok.is(tok::kw__Atomic)); + AtomicII = Tok.getIdentifierInfo(); + AtomicII->revertTokenIDToIdentifier(); + Tok.setKind(tok::identifier); + } + ~PreserveAtomicIdentifierInfoRAII() { + if (!AtomicII) + return; + AtomicII->revertIdentifierToTokenID(tok::kw__Atomic); + } + IdentifierInfo *AtomicII; + }; + + // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL + // implementation for VS2013 uses _Atomic as an identifier for one of the + // classes in . When we are parsing 'struct _Atomic', don't consider + // '_Atomic' to be a keyword. We are careful to undo this so that clang can + // use '_Atomic' in its own header files. + bool ShouldChangeAtomicToIdentifier = getLangOpts().MSVCCompat && + Tok.is(tok::kw__Atomic) && + TagType == DeclSpec::TST_struct; + PreserveAtomicIdentifierInfoRAII AtomicTokenGuard( + Tok, ShouldChangeAtomicToIdentifier); + + // Parse the (optional) nested-name-specifier. + CXXScopeSpec &SS = DS.getTypeSpecScope(); + if (getLangOpts().CPlusPlus) { + // "FOO : BAR" is not a potential typo for "FOO::BAR". In this context it + // is a base-specifier-list. + ColonProtectionRAIIObject X(*this); + + CXXScopeSpec Spec; + bool HasValidSpec = true; + if (ParseOptionalCXXScopeSpecifier(Spec, /*ObjectType=*/nullptr, + /*ObjectHadErrors=*/false, + EnteringContext)) { + DS.SetTypeSpecError(); + HasValidSpec = false; + } + if (Spec.isSet()) + if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) { + Diag(Tok, diag::err_expected) << tok::identifier; + HasValidSpec = false; + } + if (HasValidSpec) + SS = Spec; + } + + TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; + + auto RecoverFromUndeclaredTemplateName = [&](IdentifierInfo *Name, + SourceLocation NameLoc, + SourceRange TemplateArgRange, + bool KnownUndeclared) { + Diag(NameLoc, diag::err_explicit_spec_non_template) + << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) + << TagTokKind << Name << TemplateArgRange << KnownUndeclared; + + // Strip off the last template parameter list if it was empty, since + // we've removed its template argument list. + if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) { + if (TemplateParams->size() > 1) { + TemplateParams->pop_back(); + } else { + TemplateParams = nullptr; + const_cast(TemplateInfo).Kind = + ParsedTemplateInfo::NonTemplate; + } + } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { + // Pretend this is just a forward declaration. + TemplateParams = nullptr; + const_cast(TemplateInfo).Kind = + ParsedTemplateInfo::NonTemplate; + const_cast(TemplateInfo).TemplateLoc = + SourceLocation(); + const_cast(TemplateInfo).ExternLoc = + SourceLocation(); + } + }; + + // Parse the (optional) class name or simple-template-id. + IdentifierInfo *Name = nullptr; + SourceLocation NameLoc; + TemplateIdAnnotation *TemplateId = nullptr; + if (Tok.is(tok::identifier)) { + Name = Tok.getIdentifierInfo(); + NameLoc = ConsumeToken(); + + if (Tok.is(tok::less) && getLangOpts().CPlusPlus) { + // The name was supposed to refer to a template, but didn't. + // Eat the template argument list and try to continue parsing this as + // a class (or template thereof). + TemplateArgList TemplateArgs; + SourceLocation LAngleLoc, RAngleLoc; + if (ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs, + RAngleLoc)) { + // We couldn't parse the template argument list at all, so don't + // try to give any location information for the list. + LAngleLoc = RAngleLoc = SourceLocation(); + } + RecoverFromUndeclaredTemplateName( + Name, NameLoc, SourceRange(LAngleLoc, RAngleLoc), false); + } + } else if (Tok.is(tok::annot_template_id)) { + TemplateId = takeTemplateIdAnnotation(Tok); + NameLoc = ConsumeAnnotationToken(); + + if (TemplateId->Kind == TNK_Undeclared_template) { + // Try to resolve the template name to a type template. May update Kind. + Actions.ActOnUndeclaredTypeTemplateName( + getCurScope(), TemplateId->Template, TemplateId->Kind, NameLoc, Name); + if (TemplateId->Kind == TNK_Undeclared_template) { + RecoverFromUndeclaredTemplateName( + Name, NameLoc, + SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc), true); + TemplateId = nullptr; + } + } + + if (TemplateId && !TemplateId->mightBeType()) { + // The template-name in the simple-template-id refers to + // something other than a type template. Give an appropriate + // error message and skip to the ';'. + SourceRange Range(NameLoc); + if (SS.isNotEmpty()) + Range.setBegin(SS.getBeginLoc()); + + // FIXME: Name may be null here. + Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template) + << TemplateId->Name << static_cast(TemplateId->Kind) << Range; + + DS.SetTypeSpecError(); + SkipUntil(tok::semi, StopBeforeMatch); + return; + } + } + + // There are four options here. + // - If we are in a trailing return type, this is always just a reference, + // and we must not try to parse a definition. For instance, + // [] () -> struct S { }; + // does not define a type. + // - If we have 'struct foo {...', 'struct foo :...', + // 'struct foo final :' or 'struct foo final {', then this is a definition. + // - If we have 'struct foo;', then this is either a forward declaration + // or a friend declaration, which have to be treated differently. + // - Otherwise we have something like 'struct foo xyz', a reference. + // + // We also detect these erroneous cases to provide better diagnostic for + // C++11 attributes parsing. + // - attributes follow class name: + // struct foo [[]] {}; + // - attributes appear before or after 'final': + // struct foo [[]] final [[]] {}; + // + // However, in type-specifier-seq's, things look like declarations but are + // just references, e.g. + // new struct s; + // or + // &T::operator struct s; + // For these, DSC is DeclSpecContext::DSC_type_specifier or + // DeclSpecContext::DSC_alias_declaration. + + // If there are attributes after class name, parse them. + MaybeParseCXX11Attributes(Attributes); + + const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); + Sema::TagUseKind TUK; + if (isDefiningTypeSpecifierContext(DSC) == AllowDefiningTypeSpec::No || + (getLangOpts().OpenMP && OpenMPDirectiveParsing)) + TUK = Sema::TUK_Reference; + else if (Tok.is(tok::l_brace) || + (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || + (isCXX11FinalKeyword() && + (NextToken().is(tok::l_brace) || NextToken().is(tok::colon)))) { + if (DS.isFriendSpecified()) { + // C++ [class.friend]p2: + // A class shall not be defined in a friend declaration. + Diag(Tok.getLocation(), diag::err_friend_decl_defines_type) + << SourceRange(DS.getFriendSpecLoc()); + + // Skip everything up to the semicolon, so that this looks like a proper + // friend class (or template thereof) declaration. + SkipUntil(tok::semi, StopBeforeMatch); + TUK = Sema::TUK_Friend; + } else { + // Okay, this is a class definition. + TUK = Sema::TUK_Definition; + } + } else if (isCXX11FinalKeyword() && (NextToken().is(tok::l_square) || + NextToken().is(tok::kw_alignas))) { + // We can't tell if this is a definition or reference + // until we skipped the 'final' and C++11 attribute specifiers. + TentativeParsingAction PA(*this); + + // Skip the 'final' keyword. + ConsumeToken(); + + // Skip C++11 attribute specifiers. + while (true) { + if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) { + ConsumeBracket(); + if (!SkipUntil(tok::r_square, StopAtSemi)) + break; + } else if (Tok.is(tok::kw_alignas) && NextToken().is(tok::l_paren)) { + ConsumeToken(); + ConsumeParen(); + if (!SkipUntil(tok::r_paren, StopAtSemi)) + break; + } else { + break; + } + } + + if (Tok.isOneOf(tok::l_brace, tok::colon)) + TUK = Sema::TUK_Definition; + else + TUK = Sema::TUK_Reference; + + PA.Revert(); + } else if (!isTypeSpecifier(DSC) && + (Tok.is(tok::semi) || + (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) { + TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration; + if (Tok.isNot(tok::semi)) { + const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy(); + // A semicolon was missing after this declaration. Diagnose and recover. + ExpectAndConsume(tok::semi, diag::err_expected_after, + DeclSpec::getSpecifierName(TagType, PPol)); + PP.EnterToken(Tok, /*IsReinject*/true); + Tok.setKind(tok::semi); + } + } else + TUK = Sema::TUK_Reference; + + // Forbid misplaced attributes. In cases of a reference, we pass attributes + // to caller to handle. + if (TUK != Sema::TUK_Reference) { + // If this is not a reference, then the only possible + // valid place for C++11 attributes to appear here + // is between class-key and class-name. If there are + // any attributes after class-name, we try a fixit to move + // them to the right place. + SourceRange AttrRange = Attributes.Range; + if (AttrRange.isValid()) { + Diag(AttrRange.getBegin(), diag::err_attributes_not_allowed) + << AttrRange + << FixItHint::CreateInsertionFromRange(AttrFixitLoc, + CharSourceRange(AttrRange, true)) + << FixItHint::CreateRemoval(AttrRange); + + // Recover by adding misplaced attributes to the attribute list + // of the class so they can be applied on the class later. + attrs.takeAllFrom(Attributes); + } + } + + // If this is an elaborated type specifier, and we delayed + // diagnostics before, just merge them into the current pool. + if (shouldDelayDiagsInTag) { + diagsFromTag.done(); + if (TUK == Sema::TUK_Reference) + diagsFromTag.redelay(); + } + + if (!Name && !TemplateId && (DS.getTypeSpecType() == DeclSpec::TST_error || + TUK != Sema::TUK_Definition)) { + if (DS.getTypeSpecType() != DeclSpec::TST_error) { + // We have a declaration or reference to an anonymous class. + Diag(StartLoc, diag::err_anon_type_definition) + << DeclSpec::getSpecifierName(TagType, Policy); + } + + // If we are parsing a definition and stop at a base-clause, continue on + // until the semicolon. Continuing from the comma will just trick us into + // thinking we are seeing a variable declaration. + if (TUK == Sema::TUK_Definition && Tok.is(tok::colon)) + SkipUntil(tok::semi, StopBeforeMatch); + else + SkipUntil(tok::comma, StopAtSemi); + return; + } + + // Create the tag portion of the class or class template. + DeclResult TagOrTempResult = true; // invalid + TypeResult TypeResult = true; // invalid + + bool Owned = false; + Sema::SkipBodyInfo SkipBody; + if (TemplateId) { + // Explicit specialization, class template partial specialization, + // or explicit instantiation. + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + if (TemplateId->isInvalid()) { + // Can't build the declaration. + } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && + TUK == Sema::TUK_Declaration) { + // This is an explicit instantiation of a class template. + ProhibitAttributes(attrs); + + TagOrTempResult = Actions.ActOnExplicitInstantiation( + getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, + TagType, StartLoc, SS, TemplateId->Template, + TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, + TemplateId->RAngleLoc, attrs); + + // Friend template-ids are treated as references unless + // they have template headers, in which case they're ill-formed + // (FIXME: "template friend class A::B;"). + // We diagnose this error in ActOnClassTemplateSpecialization. + } else if (TUK == Sema::TUK_Reference || + (TUK == Sema::TUK_Friend && + TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) { + ProhibitAttributes(attrs); + TypeResult = Actions.ActOnTagTemplateIdType(TUK, TagType, StartLoc, + SS, + TemplateId->TemplateKWLoc, + TemplateId->Template, + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->RAngleLoc); + } else { + // This is an explicit specialization or a class template + // partial specialization. + TemplateParameterLists FakedParamLists; + if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { + // This looks like an explicit instantiation, because we have + // something like + // + // template class Foo + // + // but it actually has a definition. Most likely, this was + // meant to be an explicit specialization, but the user forgot + // the '<>' after 'template'. + // It this is friend declaration however, since it cannot have a + // template header, it is most likely that the user meant to + // remove the 'template' keyword. + assert((TUK == Sema::TUK_Definition || TUK == Sema::TUK_Friend) && + "Expected a definition here"); + + if (TUK == Sema::TUK_Friend) { + Diag(DS.getFriendSpecLoc(), diag::err_friend_explicit_instantiation); + TemplateParams = nullptr; + } else { + SourceLocation LAngleLoc = + PP.getLocForEndOfToken(TemplateInfo.TemplateLoc); + Diag(TemplateId->TemplateNameLoc, + diag::err_explicit_instantiation_with_definition) + << SourceRange(TemplateInfo.TemplateLoc) + << FixItHint::CreateInsertion(LAngleLoc, "<>"); + + // Create a fake template parameter list that contains only + // "template<>", so that we treat this construct as a class + // template specialization. + FakedParamLists.push_back(Actions.ActOnTemplateParameterList( + 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, None, + LAngleLoc, nullptr)); + TemplateParams = &FakedParamLists; + } + } + + // Build the class template specialization. + TagOrTempResult = Actions.ActOnClassTemplateSpecialization( + getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(), + SS, *TemplateId, attrs, + MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] + : nullptr, + TemplateParams ? TemplateParams->size() : 0), + &SkipBody); + } + } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && + TUK == Sema::TUK_Declaration) { + // Explicit instantiation of a member of a class template + // specialization, e.g., + // + // template struct Outer::Inner; + // + ProhibitAttributes(attrs); + + TagOrTempResult = Actions.ActOnExplicitInstantiation( + getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, + TagType, StartLoc, SS, Name, NameLoc, attrs); + } else if (TUK == Sema::TUK_Friend && + TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) { + ProhibitAttributes(attrs); + + TagOrTempResult = Actions.ActOnTemplatedFriendTag( + getCurScope(), DS.getFriendSpecLoc(), TagType, StartLoc, SS, Name, + NameLoc, attrs, + MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, + TemplateParams ? TemplateParams->size() : 0)); + } else { + if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition) + ProhibitAttributes(attrs); + + if (TUK == Sema::TUK_Definition && + TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { + // If the declarator-id is not a template-id, issue a diagnostic and + // recover by ignoring the 'template' keyword. + Diag(Tok, diag::err_template_defn_explicit_instantiation) + << 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc); + TemplateParams = nullptr; + } + + bool IsDependent = false; + + // Don't pass down template parameter lists if this is just a tag + // reference. For example, we don't need the template parameters here: + // template class A *makeA(T t); + MultiTemplateParamsArg TParams; + if (TUK != Sema::TUK_Reference && TemplateParams) + TParams = + MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size()); + + stripTypeAttributesOffDeclSpec(attrs, DS, TUK); + + // Declaration or definition of a class type + TagOrTempResult = Actions.ActOnTag( + getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, attrs, AS, + DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, + SourceLocation(), false, clang::TypeResult(), + DSC == DeclSpecContext::DSC_type_specifier, + DSC == DeclSpecContext::DSC_template_param || + DSC == DeclSpecContext::DSC_template_type_arg, + &SkipBody); + + // If ActOnTag said the type was dependent, try again with the + // less common call. + if (IsDependent) { + assert(TUK == Sema::TUK_Reference || TUK == Sema::TUK_Friend); + TypeResult = Actions.ActOnDependentTag(getCurScope(), TagType, TUK, + SS, Name, StartLoc, NameLoc); + } + } + + // If there is a body, parse it and inform the actions module. + if (TUK == Sema::TUK_Definition) { + assert(Tok.is(tok::l_brace) || + (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || + isCXX11FinalKeyword()); + if (SkipBody.ShouldSkip) + SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType, + TagOrTempResult.get()); + else if (getLangOpts().CPlusPlus) + ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType, + TagOrTempResult.get()); + else { + // Parse the definition body. + ParseInterfaceBody(StartLoc, AttrFixitLoc, attrs, TagType, TagOrTempResult.get()); + if (SkipBody.CheckSameAsPrevious && + !Actions.ActOnDuplicateDefinition(DS, TagOrTempResult.get(), + SkipBody)) { + DS.SetTypeSpecError(); + return; + } + } + } + + if (!TagOrTempResult.isInvalid()) + // Delayed processing of attributes. + Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs); + + const char *PrevSpec = nullptr; + unsigned DiagID; + bool Result; + if (!TypeResult.isInvalid()) { + Result = DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, + NameLoc.isValid() ? NameLoc : StartLoc, + PrevSpec, DiagID, TypeResult.get(), Policy); + } else if (!TagOrTempResult.isInvalid()) { + Result = DS.SetTypeSpecType(TagType, StartLoc, + NameLoc.isValid() ? NameLoc : StartLoc, + PrevSpec, DiagID, TagOrTempResult.get(), Owned, + Policy); + } else { + DS.SetTypeSpecError(); + return; + } + + if (Result) + Diag(StartLoc, DiagID) << PrevSpec; + + // At this point, we've successfully parsed a class-specifier in 'definition' + // form (e.g. "struct foo { int x; }". While we could just return here, we're + // going to look at what comes after it to improve error recovery. If an + // impossible token occurs next, we assume that the programmer forgot a ; at + // the end of the declaration and recover that way. + // + // Also enforce C++ [temp]p3: + // In a template-declaration which defines a class, no declarator + // is permitted. + // + // After a type-specifier, we don't expect a semicolon. This only happens in + // C, since definitions are not permitted in this context in C++. + if (TUK == Sema::TUK_Definition && + (getLangOpts().CPlusPlus || !isTypeSpecifier(DSC)) && + (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) { + if (Tok.isNot(tok::semi)) { + const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy(); + ExpectAndConsume(tok::semi, diag::err_expected_after, + DeclSpec::getSpecifierName(TagType, PPol)); + // Push this token back into the preprocessor and change our current token + // to ';' so that the rest of the code recovers as though there were an + // ';' after the definition. + PP.EnterToken(Tok, /*IsReinject=*/true); + Tok.setKind(tok::semi); + } + } +} + /// ParseEnumBody - Parse a {} enclosed enumerator-list. /// enumerator-list: /// enumerator @@ -4958,6 +5675,8 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const { // typedef-name case tok::annot_typename: + + case tok::kw_interface: return true; } } @@ -5036,6 +5755,7 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw_union: // enum-specifier case tok::kw_enum: + case tok::kw_interface: // type-qualifier case tok::kw_const: @@ -5203,6 +5923,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw___interface: // enum-specifier case tok::kw_enum: + case tok::kw_interface: // type-qualifier case tok::kw_const: @@ -5664,6 +6385,27 @@ static bool isPipeDeclerator(const Declarator &D) { return false; } +bool Parser::IsBSCMethodAmbiguous() { + assert(NextToken().isNot(tok::eof)); + if (GetLookAheadToken(2).isNot(tok::coloncolon)) { + bool FlagUnsigned = (Tok.is(tok::kw_unsigned) && + NextToken().isOneOf(tok::kw_int, tok::kw_short, + tok::kw_long, tok::kw_unsigned)); + bool FlagLong = + (Tok.is(tok::kw_long) && + NextToken().isOneOf(tok::kw_int, tok::kw_long, tok::kw_unsigned)); + bool FlagShort = + (Tok.is(tok::kw_short) && + NextToken().isOneOf(tok::kw_short, tok::kw_int, tok::kw_unsigned)); + bool FlagInt = + (Tok.is(tok::kw_int) && + NextToken().isOneOf(tok::kw_short, tok::kw_long, tok::kw_unsigned)); + if (FlagUnsigned || FlagLong || FlagShort || FlagInt) + return true; + } + return false; +} + /// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator /// is parsed by the function passed to it. Pass null, and the direct-declarator /// isn't parsed at all, making this function effectively parse the C++ @@ -5695,13 +6437,13 @@ void Parser::ParseDeclaratorInternal(Declarator &D, D.setExtension(); // BSC - if (getLangOpts().BSC && (NextToken().is(tok::coloncolon) || GetLookAheadToken(2).is(tok::coloncolon))) { + if (getLangOpts().BSC && FindUntil(tok::coloncolon)) { BSCScopeSpec BSS(*this); ParseBSCScopeSpecifiers(BSS); TryConsumeToken(tok::coloncolon); D.setBSCScopeSpec(&BSS); - Actions.ConvertBSCScopeSpecToType(D, BSS.getBeginLoc()); + Actions.ConvertBSCScopeSpecToType(D, BSS.getBeginLoc(), true); (this->*DirectDeclParser)(D); return; } @@ -6537,20 +7279,20 @@ void Parser::ParseFunctionDeclarator(Declarator &D, if (Tok.isNot(tok::r_paren)) { const Type *typePtr = nullptr; if (!D.getExtendedType().isNull()) { - typePtr = D.getExtendedType().getTypePtr(); + typePtr = D.getExtendedType().getTypePtrOrNull(); if (typePtr) - typePtr = typePtr->getCanonicalTypeUnqualified().getTypePtr(); + typePtr = typePtr->getCanonicalTypeUnqualified().getTypePtrOrNull(); } ParseParameterDeclarationClause(D.getContext(), FirstArgAttrs, ParamInfo, EllipsisLoc, typePtr); - } - else if (RequiresArg) + } else if (RequiresArg) Diag(Tok, diag::err_argument_required_after_attribute); - + if (ParamInfo.size() > 0) { - ParmVarDecl* PD = dyn_cast_or_null(ParamInfo.data()[0].Param); - if (PD && D.getBSCScopeSpec()) - D.hasThisParam = PD->isThisParam; + ParmVarDecl *PD = + dyn_cast_or_null(ParamInfo.data()[0].Param); + if (PD && !D.getExtendedType().isNull()) + D.HasThisParam = PD->IsThisParam; } HasProto = ParamInfo.size() || getLangOpts().CPlusPlus || getLangOpts().OpenCL; @@ -6799,11 +7541,9 @@ void Parser::ParseFunctionDeclaratorIdentifierList( /// [C++11] attribute-specifier-seq parameter-declaration /// void Parser::ParseParameterDeclarationClause( - DeclaratorContext DeclaratorCtx, - ParsedAttributes &FirstArgAttrs, - SmallVectorImpl &ParamInfo, - SourceLocation &EllipsisLoc, - const Type *typePtr) { + DeclaratorContext DeclaratorCtx, ParsedAttributes &FirstArgAttrs, + SmallVectorImpl &ParamInfo, + SourceLocation &EllipsisLoc, const Type *typePtr) { // Avoid exceeding the maximum function scope depth. // See https://bugs.llvm.org/show_bug.cgi?id=19607 @@ -6923,7 +7663,8 @@ void Parser::ParseParameterDeclarationClause( } // Inform the actions module about the parameter declarator, so it gets // added to the current scope. - Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator, ParamInfo.size(), typePtr); + Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator, + ParamInfo.size(), typePtr); // Parse the default argument, if any. We parse the default // arguments in all dialects; the semantic analysis in // ActOnParamDefaultArgument will reject the default argument in diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 88ebb59f9a607b6ce65cf5d2ede9710d987e2246..1566a37771d4d4a589c8a0e6c39189ddf9644084 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1407,6 +1407,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TagType = DeclSpec::TST_interface; else if (TagTokKind == tok::kw_class) TagType = DeclSpec::TST_class; + else if (TagTokKind == tok::kw_interface) + TagType = DeclSpec::TST_interface_bsc; else { assert(TagTokKind == tok::kw_union && "Not a class specifier"); TagType = DeclSpec::TST_union; @@ -3206,10 +3208,12 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, SourceLocation AttrFixitLoc, ParsedAttributesWithRange &Attrs, unsigned TagType, Decl *TagDecl) { + // TODO: interface not here assert((TagType == DeclSpec::TST_struct || TagType == DeclSpec::TST_interface || TagType == DeclSpec::TST_union || - TagType == DeclSpec::TST_class) && "Invalid TagType!"); + TagType == DeclSpec::TST_class || + TagType == DeclSpec::TST_interface_bsc) && "Invalid TagType!"); llvm::TimeTraceScope TimeScope("ParseClass", [&]() { if (auto *TD = dyn_cast_or_null(TagDecl)) diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 6acf76d713fde1a915505357463f6a8103cb914d..678bfd7d1b3630aa773405ba5be9af8b29334b1d 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -909,12 +909,11 @@ class CastExpressionIdValidator final : public CorrectionCandidateCallback { /// '__is_rvalue_expr' /// \endverbatim /// -ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, - bool isAddressOfOperand, - bool &NotCastExpr, - TypeCastState isTypeCast, - bool isVectorLiteral, - bool *NotPrimaryExpression) { +ExprResult +Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, + bool &NotCastExpr, TypeCastState isTypeCast, + bool isVectorLiteral, bool *NotPrimaryExpression, + QualType T, bool HasBSCScopeSpce) { ExprResult Res; tok::TokenKind SavedKind = Tok.getKind(); auto SavedType = PreferredType; @@ -1036,10 +1035,38 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super)); return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast, isVectorLiteral, NotPrimaryExpression); - + case tok::kw_union: + case tok::kw_enum: + case tok::kw_struct: + if (getLangOpts().BSC && FindUntil(tok::coloncolon)) { + ParsingDeclSpec BSS(*this); + ParseBSCScopeSpecifiers(BSS); + ParsingDeclarator D(*this, BSS, DeclaratorContext::File); + D.setBSCScopeSpec(&BSS); + QualType T = Actions.ConvertBSCScopeSpecToType( + D, BSS.getBeginLoc(), false); // get scope type for BSC + HasBSCScopeSpce = TryConsumeToken(tok::coloncolon); + return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, + isTypeCast, isVectorLiteral, + NotPrimaryExpression, T, HasBSCScopeSpce); + } + // Fall through; this isn't a message send. + LLVM_FALLTHROUGH; case tok::identifier: { // primary-expression: identifier // unqualified-id: identifier // constant: enumeration-constant + if (getLangOpts().BSC && FindUntil(tok::coloncolon)) { + ParsingDeclSpec BSS(*this); + ParseBSCScopeSpecifiers(BSS); + ParsingDeclarator D(*this, BSS, DeclaratorContext::File); + D.setBSCScopeSpec(&BSS); + QualType T = Actions.ConvertBSCScopeSpecToType( + D, BSS.getBeginLoc(), false); // get scope type for BSC + HasBSCScopeSpce = TryConsumeToken(tok::coloncolon); + return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, + isTypeCast, isVectorLiteral, + NotPrimaryExpression, T, HasBSCScopeSpce); + } // Turn a potentially qualified name into a annot_typename or // annot_cxxscope if it would be valid. This handles things like x::y, etc. if (getLangOpts().CPlusPlus) { @@ -1251,7 +1278,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren), isAddressOfOperand, &Validator, /*IsInlineAsmIdentifier=*/false, - Tok.is(tok::r_paren) ? nullptr : &Replacement); + Tok.is(tok::r_paren) ? nullptr : &Replacement, T); if (!Res.isInvalid() && Res.isUnset()) { UnconsumeToken(Replacement); return ParseCastExpression(ParseKind, isAddressOfOperand, @@ -1281,6 +1308,12 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind); ConsumeToken(); break; + + case tok::kw_interface: + case tok::kw_implements: + llvm::outs() << "You are parsing bsc keywords!!!" << "\n"; + break; + case tok::string_literal: // primary-expression: string-literal case tok::wide_string_literal: case tok::utf8_string_literal: @@ -1525,6 +1558,18 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t: #include "clang/Basic/OpenCLImageTypes.def" { + if (getLangOpts().BSC && FindUntil(tok::coloncolon)) { + ParsingDeclSpec BSS(*this); + ParseBSCScopeSpecifiers(BSS); + ParsingDeclarator D(*this, BSS, DeclaratorContext::File); + D.setBSCScopeSpec(&BSS); + QualType T = Actions.ConvertBSCScopeSpecToType( + D, BSS.getBeginLoc(), false); // get scope type for BSC + HasBSCScopeSpce = TryConsumeToken(tok::coloncolon); + return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, + isTypeCast, isVectorLiteral, + NotPrimaryExpression, T, HasBSCScopeSpce); + } if (!getLangOpts().CPlusPlus) { Diag(Tok, diag::err_expected_expression); return ExprError(); @@ -1806,6 +1851,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, // These can be followed by postfix-expr pieces. PreferredType = SavedType; + if (Res.get()) + Res.get()->HasBSCScopeSpce = HasBSCScopeSpce; Res = ParsePostfixExpressionSuffix(Res); if (getLangOpts().OpenCL) if (Expr *PostfixExpr = Res.get()) { diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 4b5703d79f28e49f4a9add23e46d1f237139e01c..aa0d2bb0c47f117e2161b8da940721885b9b7824 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -152,7 +152,7 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType, /// /// \returns true if there was an error parsing a scope specifier bool Parser::ParseOptionalCXXScopeSpecifier( - CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors, + CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors, bool EnteringContext, bool *MayBePseudoDestructor, bool IsTypename, IdentifierInfo **LastII, bool OnlyNamespace, bool InUsingDeclaration) { assert(getLangOpts().CPlusPlus && diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 35d3b4b718db89e4234333bfe00f221d9f928ffc..0170003db76ece0f85ebd768bb2f861b364f98a1 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -211,7 +211,9 @@ Default: if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt || (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) != ParsedStmtContext()) && - (GNUAttributeLoc.isValid() || isDeclarationStatement())) { + (GNUAttributeLoc.isValid() || + (isDeclarationStatement() && + !(getLangOpts().BSC && FindUntil(tok::coloncolon))))) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; DeclGroupPtrTy Decl; if (GNUAttributeLoc.isValid()) { diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 2a42f058b8ec452edad0a8b0167744c61023c39c..ab591c5287fc452b532c0c77a323ee880ea610b3 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -107,6 +107,25 @@ static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) { } } +bool Parser::FindUntil(tok::TokenKind FindToken) { + std::vector StopTokens {tok::l_brace, tok::semi, tok::eof, + tok::equal}; + int LookStep = 0; + tok::TokenKind KindToMatch; + + while (1) { + LookStep ++; + KindToMatch = GetLookAheadToken(LookStep).getKind(); + if (llvm::any_of(StopTokens, [KindToMatch](tok::TokenKind &Toke) { + return Toke == KindToMatch; + })) + return false; + if (FindToken == KindToMatch) { + return true; + } + } +} + bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID, StringRef Msg) { if (Tok.is(ExpectedTok) || Tok.is(tok::code_completion)) { @@ -1051,7 +1070,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, return nullptr; // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" - // declaration-specifiers init-declarator-list[opt] ';' + // declaration-specifiers init-decnlarator-list[opt] ';' if (Tok.is(tok::semi)) { auto LengthOfTSTToken = [](DeclSpec::TST TKind) { assert(DeclSpec::isDeclRep(TKind)); @@ -1066,6 +1085,8 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, return 4; case DeclSpec::TST_interface: return 9; + case DeclSpec::TST_interface_bsc: + return 9; default: llvm_unreachable("we only expect to get the length of the class/struct/union/enum"); } diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index d6639e900f7b55fd298fbe9edc8cdc502b61ee22..c1f969341e6eda5e374de574f8dfc09764e665e6 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -345,6 +345,7 @@ bool Declarator::isDeclarationOfFunction() const { case TST_auto: case TST_auto_type: case TST_bool: + case TST_This: case TST_char: case TST_char8: case TST_char16: @@ -367,6 +368,7 @@ bool Declarator::isDeclarationOfFunction() const { case TST_extint: case TST_struct: case TST_interface: + case TST_interface_bsc: case TST_union: case TST_unknown_anytype: case TST_unspecified: @@ -544,6 +546,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T, case DeclSpec::TST_unspecified: return "unspecified"; case DeclSpec::TST_void: return "void"; case DeclSpec::TST_char: return "char"; + case DeclSpec::TST_This: return "This"; case DeclSpec::TST_wchar: return Policy.MSWChar ? "__wchar_t" : "wchar_t"; case DeclSpec::TST_char8: return "char8_t"; case DeclSpec::TST_char16: return "char16_t"; @@ -567,6 +570,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T, case DeclSpec::TST_union: return "union"; case DeclSpec::TST_struct: return "struct"; case DeclSpec::TST_interface: return "__interface"; + case DeclSpec::TST_interface_bsc: return "interface"; case DeclSpec::TST_typename: return "type-name"; case DeclSpec::TST_typeofType: case DeclSpec::TST_typeofExpr: return "typeof"; @@ -823,7 +827,7 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy) { - assert(!isDeclRep(T) && !isTypeRep(T) && !isExprRep(T) && + assert(!isDeclRep(T) && (!isTypeRep(T) || T == TST_This) && !isExprRep(T) && "rep required for these type-spec kinds!"); if (TypeSpecType == TST_error) return false; diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index be04970979b388fda328af7d79dc5e45bfed2a84..9810825775c230cfb8f9dce21c79a20c847630ec 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -1903,6 +1903,8 @@ static const char *GetCompletionTypeString(QualType T, ASTContext &Context, return "union "; case TTK_Enum: return "enum "; + case TTK_Interface_bsc: + return "interface "; } } } @@ -3906,6 +3908,7 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) { if (const auto *TD = dyn_cast(D)) { switch (TD->getTagKind()) { case TTK_Interface: // fall through + case TTK_Interface_bsc: case TTK_Struct: return CXCursor_StructDecl; case TTK_Class: @@ -5376,6 +5379,7 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { case DeclSpec::TST_struct: case DeclSpec::TST_class: case DeclSpec::TST_interface: + case DeclSpec::TST_interface_bsc: Filter = &ResultBuilder::IsClassOrStruct; ContextKind = CodeCompletionContext::CCC_ClassOrStructTag; break; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 23c28150ae246d8063314cb5540b86a52765a7c7..2cc79bfe0a802e5dafa9e32147f7c554431a0333 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -616,6 +616,7 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { switch (TD->getTagKind()) { case TTK_Struct: return DeclSpec::TST_struct; case TTK_Interface: return DeclSpec::TST_interface; + case TTK_Interface_bsc: return DeclSpec::TST_interface_bsc; case TTK_Union: return DeclSpec::TST_union; case TTK_Class: return DeclSpec::TST_class; case TTK_Enum: return DeclSpec::TST_enum; @@ -810,6 +811,10 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result, FixItTagName = "__interface "; break; + case TTK_Interface_bsc: + FixItTagName = "interface "; + break; + case TTK_Union: FixItTagName = "union "; break; @@ -1479,6 +1484,11 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { if (getLangOpts().CPlusPlus && D->isOutOfLine() && !S->getFnParent()) return; + // BSCMethodDecls shouldn't be pushed into scope in BSC. + if (getLangOpts().BSC && isa(D)) { + return; + } + // Template instantiations should also not be pushed into scope. if (isa(D) && cast(D)->isFunctionTemplateSpecialization()) @@ -3675,7 +3685,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, // C: Function types need to be compatible, not identical. This handles // duplicate function decls like "void f(int); void f(enum X);" properly. - if (!getLangOpts().CPlusPlus && + if (!getLangOpts().CPlusPlus && ! getLangOpts().BSC && Context.typesAreCompatible(OldQType, NewQType)) { const FunctionType *OldFuncType = OldQType->getAs(); const FunctionType *NewFuncType = NewQType->getAs(); @@ -5764,7 +5774,8 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, D.setInvalidType(); } } else if (!D.getExtendedType().isNull()) { - DC = getASTContext().BSCDeclContextMap[D.getExtendedType().getCanonicalType().getTypePtr()]; + DC = getASTContext().BSCDeclContextMap + [D.getExtendedType().getCanonicalType().getTypePtr()]; } TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); @@ -5886,6 +5897,11 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, TemplateParamLists, AddToScope); } else { + if (D.getIsInterfaceMem()) { + Diag(D.getIdentifierLoc(), diag::err_interface_member_not_func); + D.setInvalidType(true); + //return nullptr; + } New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous, TemplateParamLists, AddToScope); } @@ -6669,7 +6685,7 @@ static bool shouldConsiderLinkage(const VarDecl *VD) { return false; if (isa(DC)) return false; - llvm_unreachable("Unexpected context"); + return false; } static bool shouldConsiderLinkage(const FunctionDecl *FD) { @@ -6679,6 +6695,8 @@ static bool shouldConsiderLinkage(const FunctionDecl *FD) { return true; if (DC->isRecord()) return false; + if (DC->isInterface()) + return false; llvm_unreachable("Unexpected context"); } @@ -8449,7 +8467,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier(); if (ConstexprKind == ConstexprSpecKind::Constinit) { SemaRef.Diag(D.getDeclSpec().getConstexprSpecLoc(), - diag::err_constexpr_wrong_decl_kind) + diag::err_constexpr_wrong_decl_kind) << static_cast(ConstexprKind); ConstexprKind = ConstexprSpecKind::Unspecified; D.getMutableDeclSpec().ClearConstexprSpec(); @@ -8458,9 +8476,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // This is a bsc method declaration. BSCMethodDecl *Ret = BSCMethodDecl::Create( - SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, - TInfo, SC, isInline, ConstexprKind, SourceLocation(), - TrailingRequiresClause); + SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC, + isInline, ConstexprKind, SourceLocation(), TrailingRequiresClause); return Ret; } bool HasPrototype = @@ -8889,6 +8906,13 @@ static Scope *getTagInjectionScope(Scope *S, const LangOptions &LangOpts) { return S; } +NamedDecl *Sema::ActOnInterfaceMemberDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParameterLists) { + D.setIsInterfaceMem(true); + NamedDecl *Member = HandleDeclarator(S, D, TemplateParameterLists); + return Member; +} + NamedDecl* Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous, @@ -8921,10 +8945,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, diag::err_invalid_thread) << DeclSpec::getSpecifierName(TSCS); - if (D.isFirstDeclarationOfMember()) - adjustMemberFunctionCC(R, D.isStaticMember(), D.isCtorOrDtor(), - D.getIdentifierLoc()); - + if (D.isFirstDeclarationOfMember()) { + if (D.getIsInterfaceMem()) { + adjustMemberFunctionCC(R, true, D.isCtorOrDtor(), + D.getIdentifierLoc()); // TODO: add bsc's abi + } else {adjustMemberFunctionCC(R, D.isStaticMember(), D.isCtorOrDtor(), + D.getIdentifierLoc());} + + } bool isFriend = false; FunctionTemplateDecl *FunctionTemplate = nullptr; bool isMemberSpecialization = false; @@ -13563,10 +13591,13 @@ void Sema::CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D) { /// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator() /// to introduce parameters into function prototype scope. -Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, int ParamSize, - const Type *typePtr) { +Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, int ParamSize, const Type *typePtr) { const DeclSpec &DS = D.getDeclSpec(); - + if (DS.getTypeSpecType() == TST_This) { + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + return CheckParameter(Context.getTranslationUnitDecl(), D.getBeginLoc(), + D.getIdentifierLoc(), D.getIdentifier(), TInfo->getType(), TInfo, SC_Register); + } // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. // C++03 [dcl.stc]p2 also permits 'auto'. @@ -13609,18 +13640,25 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, int ParamSize, // Check for redeclaration of parameters, e.g. int foo(int x, int x); IdentifierInfo *II = D.getIdentifier(); - bool isThisParam = false; - if (typePtr != nullptr && DeclarationName(II).getAsString() == "this") { + bool IsThisParam = false; + // if TypePtr is nullptr, it is not a BSCMethod + if (TypePtr && DeclarationName(II).getAsString() == "this") { if (ParamSize == 0) { - auto thisTypePtr = parmDeclType.getTypePtr()->getPointeeType()->getCanonicalTypeUnqualified().getTypePtr(); - if (typePtr == nullptr || typePtr != thisTypePtr) { + auto ThisTypePtr = parmDeclType.getTypePtrOrNull(); + if (ThisTypePtr) { + ThisTypePtr = ThisTypePtr->getPointeeType().getTypePtrOrNull(); + if (ThisTypePtr) + ThisTypePtr = + ThisTypePtr->getCanonicalTypeUnqualified().getTypePtrOrNull(); + } + if (TypePtr != ThisTypePtr) { Diag(D.getBeginLoc(), diag::err_type_unsupported) - << parmDeclType.getAsString(); + << parmDeclType.getAsString(); } - isThisParam = true; + IsThisParam = true; } else { Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name) - << GetNameForDeclarator(D).getName(); + << GetNameForDeclarator(D).getName(); } } @@ -13653,7 +13691,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, int ParamSize, ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(), D.getBeginLoc(), D.getIdentifierLoc(), II, parmDeclType, TInfo, SC); - New->isThisParam = isThisParam; + New->IsThisParam = IsThisParam; if (D.isInvalidType()) New->setInvalidDecl(); @@ -15197,6 +15235,7 @@ Sema::NonTagKind Sema::getNonTagTypeDeclKind(const Decl *PrevDecl, else if (isa(PrevDecl)) return NTK_TemplateTemplateArgument; switch (TTK) { + case TTK_Interface_bsc: case TTK_Struct: case TTK_Interface: case TTK_Class: @@ -16168,9 +16207,15 @@ CreateNewDecl: if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit())) StdBadAlloc = cast(New); - } else - New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, - cast_or_null(PrevDecl)); + } else{ + if (Kind == TTK_Interface_bsc) { + New = InterfaceDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, + cast_or_null(PrevDecl)); + } + else {New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, + cast_or_null(PrevDecl));} + } + } // C++11 [dcl.type]p3: @@ -16411,6 +16456,12 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, "Broken injected-class-name"); } +void Sema::ActOnFinishInterfaceMemberSpecification(Decl *TagDecl) { + if (!TagDecl) + return; + AdjustDeclIfTemplate(TagDecl); +} + void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, SourceRange BraceRange) { AdjustDeclIfTemplate(TagD); @@ -16419,9 +16470,11 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, // Make sure we "complete" the definition even it is invalid. if (Tag->isBeingDefined()) { - assert(Tag->isInvalidDecl() && "We should already have completed it"); + // assert(Tag->isInvalidDecl() && "We should already have completed it"); if (RecordDecl *RD = dyn_cast(Tag)) RD->completeDefinition(); + if (InterfaceDecl *ID = dyn_cast(Tag)) + ID->completeDefinition(); } if (isa(Tag)) { @@ -16578,7 +16631,7 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, /// to create a FieldDecl object for it. Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth) { - FieldDecl *Res = HandleField(S, cast_or_null(TagD), + FieldDecl *Res = HandleField(S, cast_or_null(TagD), DeclStart, D, static_cast(BitfieldWidth), /*InitStyle=*/ICIS_NoInit, AS_public); return Res; @@ -16586,7 +16639,7 @@ Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, /// HandleField - Analyze a field of a C struct or a C++ data member. /// -FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, +FieldDecl *Sema::HandleField(Scope *S, TagDecl *Record, SourceLocation DeclStart, Declarator &D, Expr *BitWidth, InClassInitStyle InitStyle, @@ -16693,7 +16746,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, /// \todo The Declarator argument is a hack. It will be removed once FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, TypeSourceInfo *TInfo, - RecordDecl *Record, SourceLocation Loc, + TagDecl *Record, SourceLocation Loc, bool Mutable, Expr *BitWidth, InClassInitStyle InitStyle, SourceLocation TSSL, @@ -16777,8 +16830,12 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, BitWidth = nullptr; // If this is declared as a bit-field, check the bit-field. if (BitWidth) { - BitWidth = VerifyBitField(Loc, II, T, Record->isMsStruct(Context), BitWidth, + if (Record->isInterfaceBSC()) { + BitWidth = VerifyBitField(Loc, II, T, cast(Record)->isMsStruct(Context), BitWidth, + &ZeroWidth).get();} else{ + BitWidth = VerifyBitField(Loc, II, T, cast(Record)->isMsStruct(Context), BitWidth, &ZeroWidth).get(); + } if (!BitWidth) { InvalidDecl = true; BitWidth = nullptr; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 27d3901d3d0f1c8038bef2489361756704ce25c7..6d029d7cc6c37b4aee6780684e6026f4c714d884 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2422,7 +2422,8 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand, CorrectionCandidateCallback *CCC, - bool IsInlineAsmIdentifier, Token *KeywordReplacement) { + bool IsInlineAsmIdentifier, Token *KeywordReplacement, + QualType T) { assert(!(IsAddressOfOperand && HasTrailingLParen) && "cannot be direct & operand and have a trailing lparen"); if (SS.isInvalid()) @@ -2472,7 +2473,6 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, if (DependentID) return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, IsAddressOfOperand, TemplateArgs); - // Perform the required lookup. LookupResult R(*this, NameInfo, (Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam) @@ -2497,7 +2497,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, IsAddressOfOperand, TemplateArgs); } else { bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl(); - LookupParsedName(R, S, &SS, !IvarLookupFollowUp); + LookupParsedName(R, S, &SS, !IvarLookupFollowUp, false, T); // If the result might be in a dependent base class, this is a dependent // id-expression. @@ -2522,7 +2522,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // This could be an implicitly declared function reference (legal in C90, // extension in C99, forbidden in C++). - if (R.empty() && HasTrailingLParen && II && !getLangOpts().CPlusPlus) { + if (R.empty() && HasTrailingLParen && II && !getLangOpts().CPlusPlus && !getLangOpts().BSC) { NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S); if (D) R.addDecl(D); } @@ -3411,19 +3411,24 @@ ExprResult Sema::BuildDeclarationNameExpr( // capture in OpenMP, or duplicated between host and device? valueKind = VK_LValue; break; - + case Decl::BSCMethod: // If we're referring to a method with an __unknown_anytype // result type, make the entire expression __unknown_anytype. // This should only be possible with a type written directly. - if (const FunctionProtoType *proto - = dyn_cast(VD->getType())) + if (const FunctionProtoType *proto = + dyn_cast(VD->getType())) if (proto->getReturnType() == Context.UnknownAnyTy) { type = Context.UnknownAnyTy; valueKind = VK_RValue; break; } - LLVM_FALLTHROUGH; + + // BSC methods are l-values if static, r-values if non-static. + if (cast(VD)->isStatic()) { + valueKind = VK_LValue; + } + break; case Decl::CXXMethod: // If we're referring to a method with an __unknown_anytype @@ -4341,6 +4346,7 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, case Type::ConstantMatrix: case Type::Record: case Type::Enum: + case Type::Interface: case Type::Elaborated: case Type::TemplateSpecialization: case Type::ObjCObject: @@ -5780,7 +5786,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, : (IsExecConfig ? 3 /* kernel function (exec config) */ : 0 /* function */); bool isBSCInstanceFunc = false; - if (FDecl) { + if (FDecl && !Fn->HasBSCScopeSpce) { BSCMethodDecl* MD = dyn_cast_or_null(FDecl); if (MD && MD->getHasThisParam()) { isBSCInstanceFunc = true; @@ -5872,7 +5878,8 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, VariadicCallType CallType = getVariadicCallType(FDecl, Proto, Fn); Invalid = GatherArgumentsForCall(Call->getBeginLoc(), FDecl, Proto, 0, Args, - AllArgs, CallType, false, false, isBSCInstanceFunc, Call); + AllArgs, CallType, false, false, + isBSCInstanceFunc, Call); if (Invalid) return true; unsigned TotalNumArgs = AllArgs.size(); @@ -5888,48 +5895,58 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, SmallVectorImpl &AllArgs, VariadicCallType CallType, bool AllowExplicit, bool IsListInitialization, - bool IsBSCInstanceFunc, CallExpr* Call) { + bool IsBSCInstanceFunc, CallExpr *Call) { unsigned NumParams = Proto->getNumParams(); bool Invalid = false; size_t ArgIx = 0; - // If the BSCMethod contains `this` parameter, the function is an instance member function, - // It does not need to explicitly pass parameters when calling, - // So we need to build an ast for `this` parameter. - if (IsBSCInstanceFunc) { - Expr* Callee = Call->getCallee(); - if (ImplicitCastExpr* ICE = dyn_cast(Callee)) { // Hack, if Callee is ImplicitCastExpr* - Expr* SE = ICE->getSubExpr(); - MemberExpr* Member = dyn_cast(SE); // MemberExpr foo.getA or foo->getA + // If the BSCMethod contains `this` parameter, the function is an instance + // member function, It does not need to explicitly pass parameters when + // calling, So we need to build an ast for `this` parameter. + if (IsBSCInstanceFunc) { + Expr *Callee = Call->getCallee(); + if (ImplicitCastExpr *ICE = dyn_cast( + Callee)) { // Hack, if Callee is ImplicitCastExpr* + Expr *SE = ICE->getSubExpr(); + MemberExpr *Member = + dyn_cast(SE); // MemberExpr foo.getA or foo->getA if (!Member) return true; - - Expr* ImplicitArg = nullptr; + + Expr *ImplicitArg = nullptr; if (Member->isArrow()) { // foo->getA - DeclRefExpr* DRE = nullptr; - if (auto BaseExpr = dyn_cast(Member->getBase())) { + DeclRefExpr *DRE = nullptr; + if (auto BaseExpr = dyn_cast(Member->getBase())) { DRE = dyn_cast(BaseExpr->getSubExpr()); - } + } if (!DRE) return true; ImplicitArg = DeclRefExpr::Create( - this->Context, DRE->getQualifierLoc(), DRE->getTemplateKeywordLoc(), - DRE->getDecl(), DRE->refersToEnclosingVariableOrCapture(), - DRE->getNameInfo(), DRE->getType(), VK_RValue, - DRE->getFoundDecl(), nullptr); + this->Context, DRE->getQualifierLoc(), DRE->getTemplateKeywordLoc(), + DRE->getDecl(), DRE->refersToEnclosingVariableOrCapture(), + DRE->getNameInfo(), DRE->getType(), VK_RValue, DRE->getFoundDecl(), + nullptr); } else { // foo.getA - DeclRefExpr* DRE = dyn_cast(Member->getBase()); + DeclRefExpr *DRE = dyn_cast(Member->getBase()); if (!DRE) return true; - ImplicitArg = UnaryOperator::Create( - this->Context, DRE, UO_AddrOf, this->Context.getPointerType(DRE->getType()), - VK_RValue, OK_Ordinary, SourceLocation(), false, this->CurFPFeatureOverrides()); + ImplicitArg = + UnaryOperator::Create(this->Context, DRE, UO_AddrOf, + this->Context.getPointerType(DRE->getType()), + VK_RValue, OK_Ordinary, SourceLocation(), + false, this->CurFPFeatureOverrides()); } - - const FunctionProtoType* FPT = dyn_cast(Member->getType()); - auto typeQual = FPT->getParamType(0).getTypePtr()->getPointeeType().getCVRQualifiers(); + + const FunctionProtoType *FPT = + dyn_cast(Member->getType()); + auto typeQual = FPT->getParamType(0) + .getTypePtr() + ->getPointeeType() + .getCVRQualifiers(); if (typeQual & Qualifiers::Const || typeQual & Qualifiers::Volatile) { - ImplicitCastExpr* Implict = ImplicitCastExpr::Create(this->Context, FPT->getParamType(0), CK_NoOp, ImplicitArg, nullptr, VK_RValue, FPOptionsOverride()); + ImplicitCastExpr *Implict = ImplicitCastExpr::Create( + this->Context, FPT->getParamType(0), CK_NoOp, ImplicitArg, nullptr, + VK_RValue, FPOptionsOverride()); AllArgs.push_back(Implict); } else { AllArgs.push_back(ImplicitArg); @@ -6605,6 +6622,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, ArrayRef Args, SourceLocation RParenLoc, Expr *Config, bool IsExecConfig, ADLCallKind UsesADL) { + bool HasBSCScopeSpce = Fn->HasBSCScopeSpce; FunctionDecl *FDecl = dyn_cast_or_null(NDecl); unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0); @@ -6646,6 +6664,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (Result.isInvalid()) return ExprError(); Fn = Result.get(); + Fn->HasBSCScopeSpce = HasBSCScopeSpce; // Check for a valid function type, but only if it is not a builtin which // requires custom type checking. These will be handled by diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 7c11569ddbdc3838e9d9657879046ddb9c3711b7..30a7a22583837df1dd0bfc0fc9893c195a52fc21 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -635,7 +635,7 @@ private: }; // Callback to only accept typo corrections that are either a ValueDecl or a -// and are declared in the current enum or, for a C++ classes, one of its +// and are declared in the current enum or, for a C++ classes, one of its // base classes. class EnumMemberExprValidatorCCC final : public CorrectionCandidateCallback { public: @@ -835,10 +835,9 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, } static bool LookupMemberExprInEnum(Sema &SemaRef, LookupResult &R, - Expr *BaseExpr, - const EnumType *ETy, - SourceLocation OpLoc, bool IsArrow, - CXXScopeSpec &SS, TypoExpr *&TE) { + Expr *BaseExpr, const EnumType *ETy, + SourceLocation OpLoc, bool IsArrow, + CXXScopeSpec &SS, TypoExpr *&TE) { SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange(); EnumDecl *EDecl = ETy->getDecl(); @@ -1228,18 +1227,33 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, MemberFn, FoundDecl, /*HadMultipleCandidates=*/false, MemberNameInfo, type, valueKind, OK_Ordinary); } - + if (BSCMethodDecl *MemberFn = dyn_cast(MemberDecl)) { ExprValueKind valueKind; QualType type; valueKind = VK_LValue; type = MemberFn->getType(); + if (!MemberFn->getExtendedType().isNull()) { + DeclContext *DC = + getASTContext().BSCDeclContextMap + [MemberFn->getExtendedType().getCanonicalType().getTypePtr()]; + // If this first parameter is not "this", + // it can only be called through '::'. + if (!MemberFn->getHasThisParam()) { + if (IsArrow) + Diag(OpLoc, diag::err_no_member_on_arrow) + << MemberName << DC << FixItHint::CreateReplacement(OpLoc, "::"); + else + Diag(OpLoc, diag::err_no_member_on_period) + << MemberName << DC << FixItHint::CreateReplacement(OpLoc, "::"); + } + } return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, MemberFn, FoundDecl, /*HadMultipleCandidates=*/false, MemberNameInfo, type, valueKind, OK_Ordinary); } - + assert(!isa(MemberDecl) && "member function not C++ method?"); if (EnumConstantDecl *Enum = dyn_cast(MemberDecl)) { @@ -1416,37 +1430,43 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, } if (S.getLangOpts().BSC) { - if (const BuiltinType *BTy = BaseType->getAs()) { - if (S.getASTContext().BSCDeclContextMap.find(BTy) != S.getASTContext().BSCDeclContextMap.end()) { + if (const BuiltinType *BTy = BaseType->getAs()) { + if (S.getASTContext().BSCDeclContextMap.find(BTy) != + S.getASTContext().BSCDeclContextMap.end()) { TypoExpr *TE = nullptr; auto DeclContext = S.getASTContext().BSCDeclContextMap[BTy]; // TODO: add assert - RecordDecl* Rdecl = dyn_cast(DeclContext); - const RecordType* RTy = dyn_cast(Rdecl->getTypeForDecl()); - if (LookupMemberExprInRecord(S, R, BaseExpr.get(), RTy, OpLoc, IsArrow, SS, - HasTemplateArgs, TemplateKWLoc, TE)) + RecordDecl *Rdecl = dyn_cast(DeclContext); + const RecordType *RTy = dyn_cast(Rdecl->getTypeForDecl()); + if (LookupMemberExprInRecord(S, R, BaseExpr.get(), RTy, OpLoc, IsArrow, + SS, HasTemplateArgs, TemplateKWLoc, TE)) return ExprError(); // Returning valid-but-null is how we indicate to the caller that // the lookup result was filled in. If typo correction was attempted and - // failed, the lookup result will have been cleared--that combined with the - // valid-but-null ExprResult will trigger the appropriate diagnostics. + // failed, the lookup result will have been cleared--that combined with + // the valid-but-null ExprResult will trigger the appropriate + // diagnostics. return ExprResult(TE); } } if (const EnumType *ETy = BaseType->getAs()) { - if (S.getASTContext().BSCDeclContextMap.find(ETy) != S.getASTContext().BSCDeclContextMap.end()) { + if (S.getASTContext().BSCDeclContextMap.find(ETy) != + S.getASTContext().BSCDeclContextMap.end()) { TypoExpr *TE = nullptr; // TODO: add assert - if (LookupMemberExprInEnum(S, R, BaseExpr.get(), ETy, OpLoc, IsArrow, SS, TE)) + if (LookupMemberExprInEnum(S, R, BaseExpr.get(), ETy, OpLoc, IsArrow, + SS, TE)) return ExprError(); - - if (!R.empty() && dyn_cast(R.getFoundDecl()) != nullptr) { + + if (!R.empty() && + dyn_cast(R.getFoundDecl()) != nullptr) { // Returning valid-but-null is how we indicate to the caller that - // the lookup result was filled in. If typo correction was attempted and - // failed, the lookup result will have been cleared--that combined with the - // valid-but-null ExprResult will trigger the appropriate diagnostics. + // the lookup result was filled in. If typo correction was attempted + // and failed, the lookup result will have been cleared--that combined + // with the valid-but-null ExprResult will trigger the appropriate + // diagnostics. return ExprResult(TE); } } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 2a5206ca6a974de9d0a6cf8d98d47478715a8cbb..5814d1d9a8f55b76aee9f215f74277557517f3c0 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -206,9 +206,8 @@ namespace { // Retrieve the set of identifier namespaces that correspond to a // specific kind of name lookup. -static inline unsigned getIDNS(Sema::LookupNameKind NameKind, - bool CPlusPlus, bool BSC, - bool Redeclaration) { +static inline unsigned getIDNS(Sema::LookupNameKind NameKind, bool CPlusPlus, + bool BSC, bool Redeclaration) { unsigned IDNS = 0; switch (NameKind) { case Sema::LookupObjCImplicitSelfParam: @@ -298,8 +297,8 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind, } void LookupResult::configure() { - IDNS = getIDNS(LookupKind, getSema().getLangOpts().CPlusPlus, - getSema().getLangOpts().BSC, isForRedeclaration()); + IDNS = getIDNS(LookupKind, getSema().getLangOpts().CPlusPlus, + getSema().getLangOpts().BSC, isForRedeclaration()); // If we're looking for one of the allocation or deallocation // operators, make sure that the implicitly-declared new and delete @@ -2406,7 +2405,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, /// /// @returns True if any decls were found (but possibly ambiguous) bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, - bool AllowBuiltinCreation, bool EnteringContext) { + bool AllowBuiltinCreation, bool EnteringContext, + QualType T) { if (SS && SS->isInvalid()) { // When the scope specifier is invalid, don't even look for // anything. @@ -2436,6 +2436,14 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, return false; } + if (!T.isNull() && getLangOpts().BSC) { + DeclContext *DC = getASTContext().BSCDeclContextMap[T.getCanonicalType().getTypePtr()]; + if (DC) + return LookupQualifiedName(R, DC); + else + Diag(R.getNameLoc(), diag::err_undeclared_var_use) << R.getLookupName(); + } + // Perform unqualified name lookup starting in the given scope. return LookupName(R, S, AllowBuiltinCreation); } @@ -2812,6 +2820,9 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { case Type::Builtin: break; + case Type::Interface: + break; + // -- If T is a class type (including unions), its associated // classes are: the class itself; the class of which it is // a member, if any; and its direct and indirect base classes. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 12880b95b9c6342f4ae052dc004f49098e2b6a4f..4cd76340cd9234417435dd2670a95b8bbd6d7887 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5928,6 +5928,10 @@ bool UnnamedLocalNoLinkageFinder::VisitBuiltinType(const BuiltinType*) { return false; } +bool UnnamedLocalNoLinkageFinder::VisitThisType(const ThisType*) { + return false; +} + bool UnnamedLocalNoLinkageFinder::VisitComplexType(const ComplexType* T) { return Visit(T->getElementType()); } @@ -6063,6 +6067,10 @@ bool UnnamedLocalNoLinkageFinder::VisitEnumType(const EnumType* T) { return VisitTagDecl(T->getDecl()); } +bool UnnamedLocalNoLinkageFinder::VisitInterfaceType(const InterfaceType* T) { + return VisitTagDecl(T->getDecl()); +} + bool UnnamedLocalNoLinkageFinder::VisitTemplateTypeParmType( const TemplateTypeParmType*) { return false; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index ee4316e7a632092f78ea8fac6e1df67518f523bd..8a340c809332a79abab28fdae5edbe050601628f 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1631,6 +1631,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, case Type::FunctionNoProto: case Type::Record: case Type::Enum: + case Type::Interface: case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: @@ -6074,6 +6075,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, case Type::FunctionNoProto: case Type::Record: case Type::Enum: + case Type::Interface: case Type::ObjCInterface: case Type::ObjCObject: case Type::ObjCObjectPointer: diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index a9a77cca36a02b9297134d95c5514659f75b2289..f5e75cd8426ae6942b2afd17728a8a7bc6e7e738 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2234,7 +2234,7 @@ Decl *TemplateDeclInstantiator::VisitBSCMethodDecl( BSCMethodDecl *D, TemplateParameterList *TemplateParams, Optional ClassScopeSpecializationArgs, RewriteKind FunctionRewriteKind) { - return VisitFunctionDecl(D, TemplateParams, FunctionRewriteKind); + return VisitFunctionDecl(D, TemplateParams, FunctionRewriteKind); } Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( @@ -3513,6 +3513,10 @@ Decl *TemplateDeclInstantiator::VisitRecordDecl(RecordDecl *D) { llvm_unreachable("There are only CXXRecordDecls in C++"); } +Decl *TemplateDeclInstantiator::VisitInterfaceDecl(InterfaceDecl *D) { + llvm_unreachable("There are only CXXRecordDecls in C++"); +} + Decl * TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl *D) { diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 1951aec3d17d9c2a4a90dafb713cb20584614a74..d3212ec530e2797d25a002180a49c26ec3fefd23 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -879,6 +879,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_unspecified: case TST_void: + case TST_This: case TST_char: case TST_wchar: case TST_char8: @@ -901,6 +902,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_union: case TST_struct: case TST_interface: + case TST_interface_bsc: case TST_class: case TST_auto: case TST_auto_type: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index c5dd268dd134d31cbcc6ff7bd18d7ae7a423c074..5732fd01536d3d599eac5eea77700c9576238e3a 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1282,13 +1282,15 @@ static QualType ConvertConstrainedAutoDeclSpecToType(Sema &S, DeclSpec &DS, /// to be converted, along with other associated processing state. /// \returns The type described by the declaration specifiers. This function /// never returns null. -static QualType ConvertDeclSpecToType(TypeProcessingState &state, bool BSCMethodFlag = false) { +static QualType ConvertDeclSpecToType(TypeProcessingState &state, + bool BSCMethodFlag = false) { // FIXME: Should move the logic from DeclSpec::Finish to here for validity // checking. Sema &S = state.getSema(); Declarator &declarator = state.getDeclarator(); - DeclSpec &DS = BSCMethodFlag ? *(declarator.getBSCScopeSpec()) : declarator.getMutableDeclSpec(); + DeclSpec &DS = BSCMethodFlag ? *(declarator.getBSCScopeSpec()) + : declarator.getMutableDeclSpec(); SourceLocation DeclLoc = declarator.getIdentifierLoc(); if (DeclLoc.isInvalid()) DeclLoc = DS.getBeginLoc(); @@ -1335,7 +1337,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state, bool BSCMethod break; case DeclSpec::TST_char16: assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified && - "Unknown TSS value"); + "UnknowisNulln TSS value"); Result = Context.Char16Ty; break; case DeclSpec::TST_char32: @@ -1343,6 +1345,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state, bool BSCMethod "Unknown TSS value"); Result = Context.Char32Ty; break; + case DeclSpec::TST_This: + Result = S.GetTypeFromParser(DS.getRepAsType()); + assert(!Result.isNull() && "Didn't get a type for typeof?"); + Result = Context.getThisType(Result); + break; case DeclSpec::TST_unspecified: // If this is a missing declspec in a block literal return context, then it // is inferred from the return statements inside the block. @@ -1571,6 +1578,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state, bool BSCMethod case DeclSpec::TST_enum: case DeclSpec::TST_union: case DeclSpec::TST_struct: + case DeclSpec::TST_interface_bsc: case DeclSpec::TST_interface: { TagDecl *D = dyn_cast_or_null(DS.getRepAsDecl()); if (!D) { @@ -1607,7 +1615,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state, bool BSCMethod if (Result.isNull()) { declarator.setInvalidType(true); } - + // TypeQuals handled by caller. break; } @@ -1835,7 +1843,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state, bool BSCMethod return Result; } -void Sema::ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc) { +QualType Sema::ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc, + bool AddToContextMap) { TypeProcessingState state(*this, D); bool BSCMethodFlag = true; QualType T = ConvertDeclSpecToType(state, BSCMethodFlag); @@ -1843,25 +1852,32 @@ void Sema::ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc) { if (T->isIncompleteType(&Def)) { BoundTypeDiagnoser<> Diagnoser(diag::err_typecheck_decl_incomplete_type); Diagnoser.diagnose(*this, Loc, T); - } else { + } else if (AddToContextMap) { D.setExtendedType(T); - const Type* BasedType = T.getCanonicalType().getTypePtr(); + const Type *BasedType = T.getCanonicalType().getTypePtr(); // build declcontext map - if (getASTContext().BSCDeclContextMap.find(BasedType) == getASTContext().BSCDeclContextMap.end()) { - if (const RecordType* RTy = dyn_cast(BasedType)) { // struct type or union type + if (getASTContext().BSCDeclContextMap.find(BasedType) == + getASTContext().BSCDeclContextMap.end()) { + if (const RecordType *RTy = dyn_cast( + BasedType)) { // struct type or union type getASTContext().BSCDeclContextMap[BasedType] = RTy->getDecl(); - } else if (const EnumType* ETy = dyn_cast(BasedType)) { // enum type + } else if (const EnumType *ETy = + dyn_cast(BasedType)) { // enum type getASTContext().BSCDeclContextMap[BasedType] = ETy->getDecl(); - } else if (const BuiltinType* BTy = dyn_cast(BasedType)){ // builtin type + } else if (const BuiltinType *BTy = + dyn_cast(BasedType)) { // builtin type std::string Prefix = "__"; - std::string BuiltinTypeName = Prefix + BTy->getNameAsCString(getPrintingPolicy()); - auto TmpRecord = getASTContext().buildImplicitRecord(StringRef(BuiltinTypeName)); + std::string BuiltinTypeName = + Prefix + BTy->getNameAsCString(getPrintingPolicy()); + auto TmpRecord = + getASTContext().buildImplicitRecord(StringRef(BuiltinTypeName)); TmpRecord->startDefinition(); TmpRecord->completeDefinition(); getASTContext().BSCDeclContextMap[BasedType] = TmpRecord; } } } + return T; } static std::string getPrintableNameForEntity(DeclarationName Entity) { @@ -3407,6 +3423,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, } else { switch (cast(SemaRef.CurContext)->getTagKind()) { case TTK_Enum: llvm_unreachable("unhandled tag kind"); + case TTK_Interface_bsc: case TTK_Struct: Error = Cxx ? 1 : 2; /* Struct member */ break; case TTK_Union: Error = Cxx ? 3 : 4; /* Union member */ break; case TTK_Class: Error = 5; /* Class member */ break; @@ -5932,6 +5949,11 @@ namespace { TL.expandBuiltinRange(DS.getTypeSpecWidthRange()); } } + + void VisitThisTypeLoc(ThisTypeLoc TL) { + return; + } + void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { ElaboratedTypeKeyword Keyword = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType()); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 3c68f9458e589328bd136c27d8b7cf58c0353c4d..80059f252b6d7f5240d976f3e01d97677eb57e6f 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -949,6 +949,10 @@ public: return SemaRef.Context.getTypeDeclType(Record); } + QualType RebuildInterfaceType(InterfaceDecl *Interface) { + return SemaRef.Context.getTypeDeclType(Interface); + } + /// Build a new Enum type. QualType RebuildEnumType(EnumDecl *Enum) { return SemaRef.Context.getTypeDeclType(Enum); @@ -4808,6 +4812,13 @@ QualType TreeTransform::TransformBuiltinType(TypeLocBuilder &TLB, return T.getType(); } +template +QualType TreeTransform::TransformThisType(TypeLocBuilder &TLB, + ThisTypeLoc T) { + // FIXME: recurse? + return TransformTypeSpecType(TLB, T); +} + template QualType TreeTransform::TransformComplexType(TypeLocBuilder &TLB, ComplexTypeLoc T) { @@ -6155,6 +6166,30 @@ QualType TreeTransform::TransformRecordType(TypeLocBuilder &TLB, return Result; } +template +QualType TreeTransform::TransformInterfaceType(TypeLocBuilder &TLB, + InterfaceTypeLoc TL) { + const InterfaceType *T = TL.getTypePtr(); + InterfaceDecl *Interface + = cast_or_null(getDerived().TransformDecl(TL.getNameLoc(), + T->getDecl())); + if (!Interface) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Interface != T->getDecl()) { + Result = getDerived().RebuildInterfaceType(Interface); + if (Result.isNull()) + return QualType(); + } + + InterfaceTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; +} + template QualType TreeTransform::TransformEnumType(TypeLocBuilder &TLB, EnumTypeLoc TL) { diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index feb841833f9f6e57df6ad50550ade49667794340..df65178c232665d22c54493f06d90f4f07c5e146 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -95,9 +95,7 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { break; case BuiltinType::Accum: ID = PREDEF_TYPE_ACCUM_ID; - break; - case BuiltinType::LongAccum: - ID = PREDEF_TYPE_LONG_ACCUM_ID; + break;PREDEF_TYPE_NULL_ID; break; case BuiltinType::UShortAccum: ID = PREDEF_TYPE_USHORT_ACCUM_ID; @@ -350,6 +348,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { case Decl::TypeAlias: case Decl::Enum: case Decl::Record: + case Decl::Interface: case Decl::CXXRecord: case Decl::ClassTemplateSpecialization: case Decl::ClassTemplatePartialSpecialization: diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 1f68f6bc3e386b8685686c905a228befa6803354..b4197b75c4d017ecb1853d046b41abe12899bb57 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -6495,6 +6495,10 @@ void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { } } +void TypeLocReader::VisitThisTypeLoc(ThisTypeLoc TL) { + return; +} + void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) { TL.setNameLoc(readSourceLocation()); } @@ -6678,6 +6682,10 @@ void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) { TL.setNameLoc(readSourceLocation()); } +void TypeLocReader::VisitInterfaceTypeLoc(InterfaceTypeLoc TL) { + TL.setNameLoc(readSourceLocation()); +} + void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) { TL.setAttr(ReadAttr()); } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 91ec268465daaa032dba6470f4c641e179552df7..805c47267c21ff0265bae5e9d9bd9e11cc6a7180 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -331,7 +331,9 @@ namespace clang { RedeclarableResult VisitTagDecl(TagDecl *TD); void VisitEnumDecl(EnumDecl *ED); RedeclarableResult VisitRecordDeclImpl(RecordDecl *RD); + RedeclarableResult VisitInterfaceDeclImpl(InterfaceDecl *RD); void VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); } + void VisitInterfaceDecl(InterfaceDecl *RD) {VisitInterfaceDeclImpl(RD);} RedeclarableResult VisitCXXRecordDeclImpl(CXXRecordDecl *D); void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); } RedeclarableResult VisitClassTemplateSpecializationDeclImpl( @@ -807,6 +809,24 @@ ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { return Redecl; } +ASTDeclReader::RedeclarableResult +ASTDeclReader::VisitInterfaceDeclImpl(InterfaceDecl *RD) { + RedeclarableResult Redecl = VisitTagDecl(RD); + RD->setHasFlexibleArrayMember(Record.readInt()); + RD->setAnonymousStructOrUnion(Record.readInt()); + RD->setHasObjectMember(Record.readInt()); + RD->setHasVolatileMember(Record.readInt()); + RD->setNonTrivialToPrimitiveDefaultInitialize(Record.readInt()); + RD->setNonTrivialToPrimitiveCopy(Record.readInt()); + RD->setNonTrivialToPrimitiveDestroy(Record.readInt()); + RD->setHasNonTrivialToPrimitiveDefaultInitializeCUnion(Record.readInt()); + RD->setHasNonTrivialToPrimitiveDestructCUnion(Record.readInt()); + RD->setHasNonTrivialToPrimitiveCopyCUnion(Record.readInt()); + RD->setParamDestroyedInCallee(Record.readInt()); + RD->setArgPassingRestrictions((InterfaceDecl::ArgPassingKind)Record.readInt()); + return Redecl; +} + void ASTDeclReader::VisitValueDecl(ValueDecl *VD) { VisitNamedDecl(VD); // For function declarations, defer reading the type in case the function has @@ -1962,7 +1982,8 @@ void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { void ASTDeclReader::VisitBSCMethodDecl(BSCMethodDecl *D) { VisitFunctionDecl(D); - Record.readInt(); + D->setExtendedType(Record.readQualType()); + D->setHasThisParam(Record.readInt()); } void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 40900af6f9e00744b10d0c1fc350bc028bbc1ef5..4c1f0e80416539073b67390f69ce8a2e236f8a60 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -204,6 +204,10 @@ void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { } } +void TypeLocWriter::VisitThisTypeLoc(ThisTypeLoc TL) { + return; +} + void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } @@ -396,6 +400,10 @@ void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } +void TypeLocWriter::VisitInterfaceTypeLoc(InterfaceTypeLoc TL) { + Record.AddSourceLocation(TL.getNameLoc()); +} + void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) { Record.AddAttr(TL.getAttr()); } diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index ca8d5fd323ea2c0b61950787444266212de06081..70f5002fd9d7d5d9e2864ddc98d59c1ecafc8954 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1368,16 +1368,14 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { void ASTDeclWriter::VisitBSCMethodDecl(BSCMethodDecl *D) { VisitFunctionDecl(D); - Record.AddDeclRef(D); + Record.AddTypeRef(D->getExtendedType()); + Record.push_back(D->getHasThisParam()); if (D->getDeclContext() == D->getLexicalDeclContext() && - D->getFirstDecl() == D->getMostRecentDecl() && - !D->isInvalidDecl() && - !D->hasAttrs() && - !D->isTopLevelDeclInObjCContainer() && + D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && + !D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() && D->getDeclName().getNameKind() == DeclarationName::Identifier && - !D->hasExtInfo() && - !D->hasInheritedPrototype() && + !D->hasExtInfo() && !D->hasInheritedPrototype() && D->hasWrittenPrototype()) AbbrevToUse = Writer.getDeclBSCMethodAbbrev(); @@ -2283,11 +2281,11 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); DeclCXXMethodAbbrev = Stream.EmitAbbrev(std::move(Abv)); - // Abbreviation for DECL_BSC_METHOD + // Abbreviation for DECL_BSC_METHOD Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_BSC_METHOD)); // RedeclarableDecl - Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl + Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext @@ -2302,48 +2300,50 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Identifier - Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Identifier + Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber // ValueDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DeclaratorDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart - Abv->Add(BitCodeAbbrevOp(0)); // HasExtInfo - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart + Abv->Add(BitCodeAbbrevOp(0)); // HasExtInfo + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType // FunctionDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // StorageClass - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Inline - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InlineSpecified - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // VirtualAsWritten - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Pure - Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedProto - Abv->Add(BitCodeAbbrevOp(1)); // HasWrittenProto - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Deleted - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Trivial - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // TrivialForCall - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Defaulted - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitlyDefaulted - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ImplicitReturnZero - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constexpr - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // UsesSEHTry - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // SkippedBody - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // MultiVersion - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // StorageClass + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Inline + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InlineSpecified + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // VirtualAsWritten + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Pure + Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedProto + Abv->Add(BitCodeAbbrevOp(1)); // HasWrittenProto + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Deleted + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Trivial + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // TrivialForCall + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Defaulted + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitlyDefaulted + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ImplicitReturnZero + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constexpr + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // UsesSEHTry + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // SkippedBody + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // MultiVersion + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // TemplateKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // TemplateKind // This Array slurps the rest of the record. Fortunately we want to encode // (nearly) all the remaining (variable number of) fields in the same way. // // This is the function template information if any, then - // NumParams and Params[] from FunctionDecl, and - // NumOverriddenMethods, OverriddenMethods[] from BSCMethodDecl. + // NumParams and Params[] from FunctionDecl // // Add an AbbrevOp for 'size then elements' and use it here. Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); + // BSCMethodDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ExtendedType + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasThisParam DeclBSCMethodAbbrev = Stream.EmitAbbrev(std::move(Abv)); // Abbreviation for EXPR_DECL_REF diff --git a/clang/test/BSC/Driver/std_option.cbs b/clang/test/BSC/Driver/std_option.cbs new file mode 100644 index 0000000000000000000000000000000000000000..d60bdae7ad7defa01022c741e6e39ec889f7ad1e --- /dev/null +++ b/clang/test/BSC/Driver/std_option.cbs @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c11 -verify %s +// RUN: %clang_cc1 -std=c89 -verify %s +// RUN: %clang_cc1 -std=c99 -verify %s +// RUN: %clang_cc1 -std=c17 -verify %s + +struct Foo { +}; +// expected-error@+2 {{cannot combine with previous 'int' declaration specifier}} +// expected-error@+1 {{expected identifier or '('}} +int struct Foo::getA(struct Foo* this) { + return 1; +} diff --git a/clang/test/BSC/Method/BuiltInType/int_conflict_param_type.cbs b/clang/test/BSC/Method/BuiltInType/int_conflict_param_type.cbs new file mode 100644 index 0000000000000000000000000000000000000000..af4bfb2c8ad0877132f55a47368f2656043ec190 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_conflict_param_type.cbs @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -verify %s + +void int::increase(int a); // expected-note {{previous declaration is here}} +void int::increase(int* this) { // expected-error {{conflicting types for 'increase'}} + *this = *this +1; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_conflict_return_type.cbs b/clang/test/BSC/Method/BuiltInType/int_conflict_return_type.cbs new file mode 100644 index 0000000000000000000000000000000000000000..2007a3dadd2f02b6aae11ec99f016c067730bf95 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_conflict_return_type.cbs @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -verify %s + +double int::increase(int* this); // expected-note {{previous declaration is here}} +void int::increase(int* this) { // expected-error {{conflicting types for 'increase'}} + *this = *this +1; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_function_call.cbs b/clang/test/BSC/Method/BuiltInType/int_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..d06846e9da52a0ce83edb60ae9f115f492d4a45e --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_function_call.cbs @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -verify %s + +void int::increase() { +} + +int main() { + int x = 1; + int *y = &x; + x.increase(); // expected-error {{no instance member named 'increase' in 'struct __int'; did you mean to use '::' instead of '.'?}} + y->increase(); // expected-error {{no instance member named 'increase' in 'struct __int'; did you mean to use '::' instead of '->'?}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs b/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs new file mode 100644 index 0000000000000000000000000000000000000000..274e6134f1029ea7cbb048eb138ab94118bbb1e0 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +int getA() { + return 1; +} + +int main() { + int (*fp)() = int::getA; // expected-error {{use of undeclared identifier 'getA'}} + int (*fp1)() = &int::getA; // expected-error {{use of undeclared identifier 'getA'}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_call.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..ff822dbe784fd94ea83bdddc3b29351cfed80f03 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_call.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +void int::increase(int* this) { // expected-note {{'increase' declared here}} + *this = *this + 1; +} + +int main() { + int x = 1; + x.increase(&x); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_many_arguments.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_many_arguments.cbs new file mode 100644 index 0000000000000000000000000000000000000000..f57769cdb58218aa6e612fe69340efd77e739fd7 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_many_arguments.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +void int::increase(int* this) { // expected-note {{'increase' declared here}} + *this = *this +1; +} + +int main() { + int x = 1; + x.increase(&x); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs new file mode 100644 index 0000000000000000000000000000000000000000..5869645b7c24023b6ef9bb6b30a0363aeb30ca6a --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +void int::increase(int* this) { + *this = *this +1; +} + +int main() { + int foo = 1; + void (*fp1)(int *) = int::increase; + void (*fp2)(int *) = &int::increase; + fp1(&foo); + fp2(&foo); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs new file mode 100644 index 0000000000000000000000000000000000000000..6b5890a2b44247855731d80b59d52dd5630bedb5 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +typedef int bscInt; + +void bscInt::increase_1(bscInt* this) { + *this = *this + 1; +} + +void int::increase_2(bscInt* this) { + *this = *this + 1; +} + +void int::increase_3(int* this) { + *this = *this + 1; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_static_function_call.cbs b/clang/test/BSC/Method/BuiltInType/int_static_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..9c747a9ed7713c88ffca994fae4b3132ac7e9c84 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_static_function_call.cbs @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +int int::getA() { + return 2; +} + +int main() { + int::getA(); + int a = int::getA(); + return a - 2; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_this_param_check.cbs b/clang/test/BSC/Method/BuiltInType/int_this_param_check.cbs new file mode 100644 index 0000000000000000000000000000000000000000..09fb8971031addb230ce803a6098c1fa5f7ac04a --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_this_param_check.cbs @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -verify %s + +void int::increase(int this) { // expected-error {{int is not supported on this target}} +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_conflict_param_type.cbs b/clang/test/BSC/Method/Enum/enum_conflict_param_type.cbs new file mode 100644 index 0000000000000000000000000000000000000000..6155a971d31a3161c93cc1aaa05cb5eabadc130d --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_conflict_param_type.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +int enum E::getA(int a); // expected-note {{previous declaration is here}} +int enum E::getA(enum E* this) { // expected-error {{conflicting types for 'getA'}} + return X4; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_conflict_return_type.cbs b/clang/test/BSC/Method/Enum/enum_conflict_return_type.cbs new file mode 100644 index 0000000000000000000000000000000000000000..b14149765fc987b533ac71883a457d2cb8f7c3d7 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_conflict_return_type.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +double enum E::getA(enum E* this); // expected-note {{previous declaration is here}} +int enum E::getA(enum E* this) { // expected-error {{conflicting types for 'getA'}} + return X4; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_function_call.cbs b/clang/test/BSC/Method/Enum/enum_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..f8cdb1f0366c4c7ae5e0ab5467b834d1fe7193d2 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_function_call.cbs @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +int enum E::getA() { + return X4; +} + +int main() { + enum E foo = X3; + enum E *f = &foo; + foo.getA(); // expected-error {{no instance member named 'getA' in 'enum E'; did you mean to use '::' instead of '.'?}} + f->getA(); // expected-error {{no instance member named 'getA' in 'enum E'; did you mean to use '::' instead of '->'?}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_function_pointer_undeclared.cbs b/clang/test/BSC/Method/Enum/enum_function_pointer_undeclared.cbs new file mode 100644 index 0000000000000000000000000000000000000000..595e5db3448af620abfc80b4ddabd9d36306239c --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_function_pointer_undeclared.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +int getA() { + return 1; +} + +int main() { + int (*fp)() = enum E::getA; // expected-error {{use of undeclared identifier 'getA'}} + int (*fp1)() = &enum E::getA; // expected-error {{use of undeclared identifier 'getA'}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_call.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..446adccb1d0420bbb8305a7808de088ca1df6211 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_instance_function_call.cbs @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +int enum E::getA(enum E* this) { // expected-note {{'getA' declared here}} + return X4; +} + + +int main() { + enum E e= X3; + e.getA(&e); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_many_arguments.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_many_arguments.cbs new file mode 100644 index 0000000000000000000000000000000000000000..fc497d300863cacca0f454083b77ea92365c985a --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_instance_function_many_arguments.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +int enum E::getA(enum E* this) { // expected-note {{'getA' declared here}} + return X4; +} + +int main() { + enum E foo = X3; + foo.getA(&foo); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs new file mode 100644 index 0000000000000000000000000000000000000000..2681e682d0d6b223695d8169027b8cee02eb9914 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +enum E { + X3, + X4 +}; + +int enum E::getA(enum E* this) { + return X4; +} + +int main() { + enum E foo = X3; + int (*fp1)(enum E *) = enum E::getA; + int (*fp2)(enum E *) = &enum E::getA; + fp1(&foo); + fp2(&foo); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs new file mode 100644 index 0000000000000000000000000000000000000000..2042dba0cef01f14ac1dae783ecdb66d74e588d4 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +typedef enum E { + X3, + X4 +}E; + +int E::getX4_1(E* this) { + return X4; +} + +int E::getX4_2(enum E* this) { + return X4; +} + +int enum E::getX4_3(enum E* this) { + return X4; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_this_param_check.cbs b/clang/test/BSC/Method/Enum/enum_this_param_check.cbs new file mode 100644 index 0000000000000000000000000000000000000000..2c68b3fa281306526c2a7fd015c72cf7b71a7835 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_this_param_check.cbs @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +int enum E::getA(enum E this); // expected-error {{enum E is not supported on this target}} + diff --git a/clang/test/BSC/Method/Struct/struct_conflict_no_param_1.cbs b/clang/test/BSC/Method/Struct/struct_conflict_no_param_1.cbs new file mode 100644 index 0000000000000000000000000000000000000000..9809668a6c97e3f7e83889a78ff14c006037cd07 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_conflict_no_param_1.cbs @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(); // expected-note {{previous declaration is here}} +int struct Foo::getA(struct Foo* this) { // expected-error {{conflicting types for 'getA'}} + return this->a; +} diff --git a/clang/test/BSC/Method/Struct/struct_conflict_no_param_2.cbs b/clang/test/BSC/Method/Struct/struct_conflict_no_param_2.cbs new file mode 100644 index 0000000000000000000000000000000000000000..9e97ea8f68452f281c5a5060de1a7b5773ffdb3e --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_conflict_no_param_2.cbs @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(); // expected-note {{previous declaration is here}} +int struct Foo::getA(struct Foo* this); // expected-error {{conflicting types for 'getA'}} diff --git a/clang/test/BSC/Method/Struct/struct_conflict_param_type.cbs b/clang/test/BSC/Method/Struct/struct_conflict_param_type.cbs new file mode 100644 index 0000000000000000000000000000000000000000..0ee0da65372b27d78d4eeeeaa10a8a946eacc85a --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_conflict_param_type.cbs @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(int a); // expected-note {{previous declaration is here}} +int struct Foo::getA(struct Foo* this) { // expected-error {{conflicting types for 'getA'}} + return this->a; +} diff --git a/clang/test/BSC/Method/Struct/struct_conflict_return_type.cbs b/clang/test/BSC/Method/Struct/struct_conflict_return_type.cbs new file mode 100644 index 0000000000000000000000000000000000000000..b294fecd1800de0af11eb83348e82b1f1e94f6fa --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_conflict_return_type.cbs @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +double struct Foo::getA(struct Foo* this); // expected-note {{previous declaration is here}} +int struct Foo::getA(struct Foo* this) { // expected-error {{conflicting types for 'getA'}} + return this->a; +} diff --git a/clang/test/BSC/Method/Struct/struct_function_call.cbs b/clang/test/BSC/Method/Struct/struct_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..7ae8e560c7585e00f9efdad3edf7ecc1464480a3 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_function_call.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; +int struct Foo::getA() { + return 1; +} + +int main() { + struct Foo foo; + struct Foo *f = &foo; + foo.getA(); // expected-error {{no instance member named 'getA' in 'struct Foo'; did you mean to use '::' instead of '.'?}} + f->getA(); // expected-error {{no instance member named 'getA' in 'struct Foo'; did you mean to use '::' instead of '->'?}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_function_undeclared.cbs b/clang/test/BSC/Method/Struct/struct_function_undeclared.cbs new file mode 100644 index 0000000000000000000000000000000000000000..5849ca25dfcccef4483f59f3ee91ecf2bd30c284 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_function_undeclared.cbs @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int getA() { + return 1; +} + +int main() { + int (*fp)() = struct Foo::getA; // expected-error {{use of undeclared identifier 'getA'}} + int (*fp1)() = &struct Foo::getA; // expected-error {{use of undeclared identifier 'getA'}} + return 0; +} diff --git a/clang/test/BSC/pending/InstanceMemberFunc.cbs b/clang/test/BSC/Method/Struct/struct_instance_function.cbs similarity index 39% rename from clang/test/BSC/pending/InstanceMemberFunc.cbs rename to clang/test/BSC/Method/Struct/struct_instance_function.cbs index 0cdd03d421b1fc8bb5c37472477e8031b79486c7..416f7e75c499a23c77a7182c2a9cc0f97ce073f0 100644 --- a/clang/test/BSC/pending/InstanceMemberFunc.cbs +++ b/clang/test/BSC/Method/Struct/struct_instance_function.cbs @@ -1,17 +1,17 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -verify %s // expected-no-diagnostics -typedef struct Foo{ + +struct Foo { int a; -}Foo; +}; -int Foo::getA(struct Foo* this) { +int struct Foo::getA(struct Foo* this) { return this->a; } + int main() { - Foo foo; - foo.a = 42; + struct Foo foo = {.a = 1}; foo.getA(); - Foo::getA(&foo); return 0; } \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_call.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..0e6a528eebfeb75e6346f6fe6385d3e8a0c0788c --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_call.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this) { // expected-note {{'getA' declared here}} + return this->a; +} + + +int main() { + struct Foo foo = {.a = 1}; + foo.getA(&foo); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_declaration.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_declaration.cbs new file mode 100644 index 0000000000000000000000000000000000000000..e6c4c2fcd2f365658c675c20a589a017cd20e4aa --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_declaration.cbs @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this); + +int main() { + struct Foo foo = {.a = 1}; + foo.getA(); + return 0; +} + +int struct Foo::getA(struct Foo* this) { + return this->a; +} diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_many_arguments.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_many_arguments.cbs new file mode 100644 index 0000000000000000000000000000000000000000..ade797cabd11981dcb909bb92bba2af8709a170f --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_many_arguments.cbs @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; +int struct Foo::getA(struct Foo* this) { // expected-note {{'getA' declared here}} + return this->a; +} + +int main() { + struct Foo foo; + foo.getA(&foo); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs new file mode 100644 index 0000000000000000000000000000000000000000..ff1fdddc42e4e7d418d4c975e4a89041a66f34fa --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this); +int struct Foo::getA(struct Foo* this); + +int main() { + struct Foo foo = {.a = 1}; + foo.getA(); + return 0; +} + +int struct Foo::getA(struct Foo* this) { + return this->a; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_not_found.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_not_found.cbs new file mode 100644 index 0000000000000000000000000000000000000000..e7665e9cb10745d8dbe66a79921363b845a6eaff --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_not_found.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this) { + return this->a; +} + + +int main() { + struct Foo foo = {.a = 1}; + foo.getB(); // expected-error {{no member named 'getB' in 'struct Foo'}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs new file mode 100644 index 0000000000000000000000000000000000000000..ebd1a859d149a3ea21c60898f4ae3d8abcaacdb2 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this) { + return this->a; +} + + +int main() { + struct Foo foo = {.a = 1}; + int (*fp1)(struct Foo *) = struct Foo::getA; + int (*fp2)(struct Foo *) = &struct Foo::getA; + fp1(&foo); + fp2(&foo); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_redefinition.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_redefinition.cbs new file mode 100644 index 0000000000000000000000000000000000000000..d8aa505bd88585a38914d3769d3d6ef5ec866c62 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_redefinition.cbs @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this) { // expected-note {{previous definition is here}} + return this->a; +} + +int struct Foo::getA(struct Foo* this) { // expected-error {{redefinition of 'getA'}} + return this->a; +} + +int main() { + struct Foo foo = {.a = 1}; + foo.getA(); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/pending/Typedef.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_with_typedef.cbs similarity index 45% rename from clang/test/BSC/pending/Typedef.cbs rename to clang/test/BSC/Method/Struct/struct_instance_function_with_typedef.cbs index ee779a449bcb2a6049519225f1c8aa8419980030..a48f320d52ff73f67dd1878c16a2fa7b3642fd7c 100644 --- a/clang/test/BSC/pending/Typedef.cbs +++ b/clang/test/BSC/Method/Struct/struct_instance_function_with_typedef.cbs @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -verify %s // expected-no-diagnostics -struct Foo { + +typedef struct Foo { int a; int b; -}; -typedef struct Foo Foo; +}Foo; int Foo::getB(Foo* this) { return this->b; @@ -14,12 +14,6 @@ int Foo::getAPlusB(struct Foo* this) { return this->a + this->b; } -int main() { - Foo foo; - foo.a = 42; - foo.b = 2023; - int b = foo.getB(); - int ab = foo.getAPlusB(); - return 0; -} - +int struct Foo::getA(struct Foo* this) { + return this->a; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_static_function_call.cbs b/clang/test/BSC/Method/Struct/struct_static_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..995c843391ff8fb32cdb55eb3cfacc7438e52b0d --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_static_function_call.cbs @@ -0,0 +1,19 @@ +// RUN: %clang %s -o %t.output +// RUN: %t.output +// expected-no-diagnostics + +struct Foo { + int a; +}; + +int struct Foo::getA() { + return 1; +} + + +int main() { + struct Foo foo = {.a = 1}; + struct Foo::getA(); + int a = struct Foo::getA(); + return a - 1; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_this_param_check.cbs b/clang/test/BSC/Method/Struct/struct_this_param_check.cbs new file mode 100644 index 0000000000000000000000000000000000000000..240cca115de781f6a75af8f761983d9abaece99a --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_this_param_check.cbs @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { +}; +int struct Foo::getA(struct Foo this) { // expected-error {{struct Foo is not supported on this target}} + return 1; +} diff --git a/clang/test/BSC/Method/Struct/struct_toplevel_func.cbs b/clang/test/BSC/Method/Struct/struct_toplevel_func.cbs new file mode 100644 index 0000000000000000000000000000000000000000..268989fa775b8fcc24f5c7388ed731b96f9a9f9f --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_toplevel_func.cbs @@ -0,0 +1,18 @@ +// RUN: %clang %s -o %t.output +// RUN: %t.output +// expected-no-diagnostics + +struct F { +}; + +int struct F::increase() { + return 2; +} + +int increase() { + return 0; +} + +int main() { + return increase(); +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_toplevel_func_not_found.cbs b/clang/test/BSC/Method/Struct/struct_toplevel_func_not_found.cbs new file mode 100644 index 0000000000000000000000000000000000000000..1086c2c0007c1dcf3b6e6a1426ccdeab2132efdf --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_toplevel_func_not_found.cbs @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -verify %s + +struct F { +}; +void struct F::increase(struct F* this) { + +} + +int main() { + increase(); // expected-warning {{implicit declaration of function 'increase' is invalid in C99}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_conflict_param_type.cbs b/clang/test/BSC/Method/Union/union_conflict_param_type.cbs new file mode 100644 index 0000000000000000000000000000000000000000..3950cd93c3b15a650ff7426162e14c9f70eaf502 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_conflict_param_type.cbs @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(int a); // expected-note {{previous declaration is here}} +int union SimpleUnion::getA(union SimpleUnion * this) { // expected-error {{conflicting types for 'getA'}} + return this->ui; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_conflict_return_type.cbs b/clang/test/BSC/Method/Union/union_conflict_return_type.cbs new file mode 100644 index 0000000000000000000000000000000000000000..bad0123c1d9ea9276ba1354b53bc0e23cb333374 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_conflict_return_type.cbs @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +double union SimpleUnion::getA(union SimpleUnion * this); // expected-note {{previous declaration is here}} +int union SimpleUnion::getA(union SimpleUnion * this) { // expected-error {{conflicting types for 'getA'}} + return this->ui; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_function_call.cbs b/clang/test/BSC/Method/Union/union_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..4ef37fe8dd1e8e7dfbf0568381e1a17024fd3ba2 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_function_call.cbs @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA() { + return 1; +} + +int main() { + union SimpleUnion foo = {.ui = 1}; + union SimpleUnion *f = &foo; + foo.getA(); // expected-error {{no instance member named 'getA' in 'union SimpleUnion'; did you mean to use '::' instead of '.'?}} + f->getA(); // expected-error {{no instance member named 'getA' in 'union SimpleUnion'; did you mean to use '::' instead of '->'?}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_function_pointer_undeclared.cbs b/clang/test/BSC/Method/Union/union_function_pointer_undeclared.cbs new file mode 100644 index 0000000000000000000000000000000000000000..8993ac904fb7014f2da6991a3c16c40629e81a7d --- /dev/null +++ b/clang/test/BSC/Method/Union/union_function_pointer_undeclared.cbs @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int getA() { + return 1; +} + +int main() { + int (*fp)() = union SimpleUnion::getA; // expected-error {{use of undeclared identifier 'getA'}} + int (*fp1)() = &union SimpleUnion::getA; // expected-error {{use of undeclared identifier 'getA'}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_instance_fucntion_many_arguments.cbs b/clang/test/BSC/Method/Union/union_instance_fucntion_many_arguments.cbs new file mode 100644 index 0000000000000000000000000000000000000000..f08e3ceb9fe5eb7175239b982a5c6ba84d389afb --- /dev/null +++ b/clang/test/BSC/Method/Union/union_instance_fucntion_many_arguments.cbs @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(union SimpleUnion * this) { // expected-note {{'getA' declared here}} + return this->ui; +} + +int main() { + union SimpleUnion u = {.ui = 1}; + u.getA(&u); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_instance_function_call.cbs b/clang/test/BSC/Method/Union/union_instance_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..e0bab4d1de389f918a418b553cd811184d103d4b --- /dev/null +++ b/clang/test/BSC/Method/Union/union_instance_function_call.cbs @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(union SimpleUnion* this) { // expected-note {{'getA' declared here}} + return this->ui; +} + + +int main() { + union SimpleUnion u = {.ui = 1}; + u.getA(&u); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_instance_function_pointer.cbs b/clang/test/BSC/Method/Union/union_instance_function_pointer.cbs new file mode 100644 index 0000000000000000000000000000000000000000..3dc1847eb71aaab9fea07ce3e3af72b269b09ac2 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_instance_function_pointer.cbs @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(union SimpleUnion * this) { + return this->ui; +} + +int main() { + union SimpleUnion foo = {.ui = 1}; + int (*fp1)(union SimpleUnion *) = union SimpleUnion::getA; + int (*fp2)(union SimpleUnion *) = &union SimpleUnion::getA; + fp1(&foo); + fp2(&foo); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_instance_function_with_typedef.cbs b/clang/test/BSC/Method/Union/union_instance_function_with_typedef.cbs new file mode 100644 index 0000000000000000000000000000000000000000..153b409a1d00078e3f66a947304c31f5586860b8 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_instance_function_with_typedef.cbs @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +typedef union SimpleUnion { + float uf; + int ui; + char uc; +}SimpleUnion; + +int SimpleUnion::getui_1(SimpleUnion* this) { + return this->ui; +} + +int SimpleUnion::getui_2(union SimpleUnion* this) { + return this->ui; +} + +int union SimpleUnion::getui_3(union SimpleUnion* this) { + return this->ui; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_this_param_check.cbs b/clang/test/BSC/Method/Union/union_this_param_check.cbs new file mode 100644 index 0000000000000000000000000000000000000000..a1a88c796d022bb0a854e9f6c0435c825560c2db --- /dev/null +++ b/clang/test/BSC/Method/Union/union_this_param_check.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(union SimpleUnion this) { // expected-error {{union SimpleUnion is not supported on this target}} + return 1; +} \ No newline at end of file diff --git a/clang/test/BSC/pending/StaticMemberFunc.cbs b/clang/test/BSC/Method/ambiguous_1.cbs similarity index 40% rename from clang/test/BSC/pending/StaticMemberFunc.cbs rename to clang/test/BSC/Method/ambiguous_1.cbs index f9b2068cfd7e0f28396081e863e993c65b432786..76aa5ce27c64bd74be347c3029c0c56fb5db68bd 100644 --- a/clang/test/BSC/pending/StaticMemberFunc.cbs +++ b/clang/test/BSC/Method/ambiguous_1.cbs @@ -1,20 +1,18 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // expected-no-diagnostics -typedef struct Foo{ - int a; -}Foo; -int Foo::s1() { +long int::getA1() { return 1; -} +}; -int Foo::s2(struct Foo* other) { - return other->a; -} +unsigned int::getA2() { + return 1; +}; + +short int::getA3() { + return 1; +}; int main() { - struct Foo x = {0}; - Foo::s1(); - Foo::s2(&x); return 0; -} \ No newline at end of file +}; diff --git a/clang/test/BSC/Method/ambiguous_2.cbs b/clang/test/BSC/Method/ambiguous_2.cbs new file mode 100644 index 0000000000000000000000000000000000000000..298ea3a8d0c81aafbe363422374a1b8c1a2bf7d5 --- /dev/null +++ b/clang/test/BSC/Method/ambiguous_2.cbs @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +long long int::getA() { // expected-error {{Ambiguous declaration of BSCMethod}} + return 1; +}; + +int main() { + return 0; +}; diff --git a/clang/test/BSC/Method/ambiguous_3.cbs b/clang/test/BSC/Method/ambiguous_3.cbs new file mode 100644 index 0000000000000000000000000000000000000000..a87e50fb8c2353f2f67f7fb774e12bf613a781aa --- /dev/null +++ b/clang/test/BSC/Method/ambiguous_3.cbs @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +short short int::getA() { // expected-error {{Ambiguous declaration of BSCMethod}} + return 1; +}; + +int main() { + return 0; +}; diff --git a/clang/test/BSC/Method/ambiguous_4.cbs b/clang/test/BSC/Method/ambiguous_4.cbs new file mode 100644 index 0000000000000000000000000000000000000000..eba2ecaff588cd61e5d6747c74ec27b37e20d988 --- /dev/null +++ b/clang/test/BSC/Method/ambiguous_4.cbs @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +unsigned long int::getA() { // expected-error {{Ambiguous declaration of BSCMethod}} + return 1; +}; + +int main() { + return 0; +}; diff --git a/clang/test/BSC/Method/definition_1.cbs b/clang/test/BSC/Method/definition_1.cbs index 0677d7e95cdcae9cd84f7dc93703f59958b3417f..02be953ea3ed97d7753273b96e47de93024da5ad 100644 --- a/clang/test/BSC/Method/definition_1.cbs +++ b/clang/test/BSC/Method/definition_1.cbs @@ -1,3 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + struct Foo1 { int a; }; diff --git a/clang/test/BSC/Method/definition_2.cbs b/clang/test/BSC/Method/definition_2.cbs index c199139b9f729192f946f80f5fa7b1dc58a8071c..93ad7fdba34a2f190e34893bf4f9a1bad6e7faf2 100644 --- a/clang/test/BSC/Method/definition_2.cbs +++ b/clang/test/BSC/Method/definition_2.cbs @@ -1,14 +1,9 @@ -int struct Foo::getA() { +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int struct Foo::getA() { // expected-error {{variable has incomplete type 'struct Foo'}} return 0; } int main() { return 0; } - -/* -definition_2.cbs:1:5: error: variable has incomplete type 'struct Foo' -int struct Foo::getA() { - ^ -1 error generated. -*/ diff --git a/clang/test/BSC/Method/definition_3.cbs b/clang/test/BSC/Method/definition_3.cbs index 3494c223d16c5a76f9f95cc3761ba666d9a1657a..13bd298fce864b16d39fadd7d27a413d880ebe97 100644 --- a/clang/test/BSC/Method/definition_3.cbs +++ b/clang/test/BSC/Method/definition_3.cbs @@ -1,16 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + struct Foo; -int struct Foo::getA() { +int struct Foo::getA() { // expected-error {{variable has incomplete type 'struct Foo'}} return 0; } int main() { return 0; } - -/* -definition_3.cbs:3:5: error: variable has incomplete type 'struct Foo' -int struct Foo::getA() { - ^ -1 error generated. -*/ diff --git a/clang/test/BSC/Method/definition_4.cbs b/clang/test/BSC/Method/definition_4.cbs index ea9aeedc9fe5c039db931790879a2c7b584ca8aa..47417394667f691eb4f1464c9132bd2806fc6101 100644 --- a/clang/test/BSC/Method/definition_4.cbs +++ b/clang/test/BSC/Method/definition_4.cbs @@ -1,14 +1,9 @@ -int void::getA() { +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int void::getA() { // expected-error {{variable has incomplete type 'void'}} return 0; } int main() { return 0; } - -/* -definition_4.cbs:1:5: error: variable has incomplete type 'void' -int void::getA() { - ^ -1 error generated. -*/ diff --git a/clang/test/BSC/ParamCheck/this_not_first_param.cbs b/clang/test/BSC/ParamCheck/this_not_first_param.cbs new file mode 100644 index 0000000000000000000000000000000000000000..7fe4902bed43b5e9a654d9e528e427aab869faa3 --- /dev/null +++ b/clang/test/BSC/ParamCheck/this_not_first_param.cbs @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -verify %s + +// struct +struct Foo { + int a; +}; + +int struct Foo::getA(int b, struct Foo* this) { // expected-error {{'this' cannot be the name of a parameter}} + return this->a; +} + +// enum +enum E { + X3, + X4 +}; + +int enum E::getA(int b, enum E* this) { // expected-error {{'this' cannot be the name of a parameter}} + return X4; +} + +// union +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(int b, union SimpleUnion* this) { // expected-error {{'this' cannot be the name of a parameter}} + return this->ui; +} + +// BuiltinType +void int::increase(int b, int* this) { // expected-error {{'this' cannot be the name of a parameter}} + *this = *this + b; +} + diff --git a/clang/test/BSC/ParamCheck/this_param_type_no_match.cbs b/clang/test/BSC/ParamCheck/this_param_type_no_match.cbs new file mode 100644 index 0000000000000000000000000000000000000000..bcb0222f9857b066e472b384957b36051c426806 --- /dev/null +++ b/clang/test/BSC/ParamCheck/this_param_type_no_match.cbs @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -verify %s + +// struct +struct Foo { + int a; +}; + +struct Bar { + int a; +}; + +int struct Foo::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} + return this->a; +} + +// enum +enum E { + X3, + X4 +}; + +int enum E::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} + return this->a; +} + +// union +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} + return this->a; +} + +// BuiltinType +int int::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} + return this->a; +} \ No newline at end of file diff --git a/clang/test/BSC/ParamCheck/this_param_with_const.cbs b/clang/test/BSC/ParamCheck/this_param_with_const.cbs new file mode 100644 index 0000000000000000000000000000000000000000..a6c7aa7e29f16c7f2a7f7c884960b35eb1f7b04a --- /dev/null +++ b/clang/test/BSC/ParamCheck/this_param_with_const.cbs @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +// struct +struct Foo { + int a; +}; + +int struct Foo::getA(const struct Foo* this) { + return this->a; +} + +// enum +enum E { + X3, + X4 +}; + +int enum E::getA(const enum E* this) { + return X4; +} + +// union +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(const union SimpleUnion* this) { + return this->ui; +} + +// BuiltinType +int int::getA(const int* this) { + return *this; +} + +int main() { + struct Foo foo ={.a = 42}; + foo.getA(); + enum E e= X3; + e.getA(); + union SimpleUnion u = {.ui = 1}; + u.getA(); + int one = 1; + one.getA(); + return 0; +} + diff --git a/clang/test/BSC/ParamCheck/this_param_with_volatile.cbs b/clang/test/BSC/ParamCheck/this_param_with_volatile.cbs new file mode 100644 index 0000000000000000000000000000000000000000..2402e40ffdbe5b6e7123334802554abe399a72d9 --- /dev/null +++ b/clang/test/BSC/ParamCheck/this_param_with_volatile.cbs @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +// struct +struct Foo { + int a; +}; + +int struct Foo::getA(volatile struct Foo* this) { + return this->a; +} + +// enum +enum E { + X3, + X4 +}; + +int enum E::getA(volatile enum E* this) { + return X4; +} + +// union +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(volatile union SimpleUnion* this) { + return this->ui; +} + +// BuiltinType +int int::getA(volatile int* this) { + return *this; +} + +int main() { + struct Foo foo ={.a = 42}; + foo.getA(); + enum E e= X3; + e.getA(); + union SimpleUnion u = {.ui = 1}; + u.getA(); + int one = 1; + one.getA(); + return 0; +} diff --git a/clang/test/BSC/pending/CallBeforeDefine.cbs b/clang/test/BSC/pending/CallBeforeDefine.cbs deleted file mode 100644 index c8e9187030a7ee4a8195ba39270a172de51fc0f8..0000000000000000000000000000000000000000 --- a/clang/test/BSC/pending/CallBeforeDefine.cbs +++ /dev/null @@ -1,17 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics -typedef struct Foo { - int a; -}Foo; - -int Foo::getA(struct Foo* this); - -int main() { - struct Foo foo; - foo.a = 42; - return foo.getA(); -} - -int Foo::getA(struct Foo* this) { - return this->a; -} \ No newline at end of file diff --git a/clang/test/BSC/pending/OverloadFunc.cbs b/clang/test/BSC/pending/OverloadFunc.cbs deleted file mode 100644 index 442a57b87669f0d6e64a3262f570b5d01e2cfe62..0000000000000000000000000000000000000000 --- a/clang/test/BSC/pending/OverloadFunc.cbs +++ /dev/null @@ -1,24 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -struct Foo { - int a; -}; -typedef struct Foo F; - -int F::f2(F* this) { -// expected-note@-1 {{previous definition is here}} -// expected-note@-2 {{passing argument to parameter 'this' here}} - return 1; -} - -int F::f2(F* this, int a) { // expected-error {{conflicting types for 'f2'}} - return a; -} - -int main(){ - Foo foo; - foo.a = 1; - foo.f2(); - foo.f2(1); // expected-warning {{incompatible integer to pointer conversion passing 'int' to parameter of type 'F *' (aka 'struct Foo *')}} - return 0; -} \ No newline at end of file diff --git a/clang/test/BSC/pending/ThisParamCheck1.cbs b/clang/test/BSC/pending/ThisParamCheck1.cbs deleted file mode 100644 index 05281fbfb1fb9aa16636449232fe2c74d5e35883..0000000000000000000000000000000000000000 --- a/clang/test/BSC/pending/ThisParamCheck1.cbs +++ /dev/null @@ -1,17 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -typedef struct Foo { - int a; -}Foo; - -typedef struct Bar { - int a; -}Bar; - -int Foo::getA(int b, struct Foo* this) { // expected-error {{'this' cannot be the name of a parameter}} - return this->a; -} - -int Foo::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} - return this->a; -} \ No newline at end of file diff --git a/clang/test/BSC/pending/ThisParamCheck2.cbs b/clang/test/BSC/pending/ThisParamCheck2.cbs deleted file mode 100644 index 1fee3762a580a10bde21b4721bce596c6822aa77..0000000000000000000000000000000000000000 --- a/clang/test/BSC/pending/ThisParamCheck2.cbs +++ /dev/null @@ -1,21 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -typedef struct Foo{ - int a; -}Foo; - -int Foo::s1() { - return 1; -} - -int Foo::s2(struct Foo* other) { - return other->a; -} - -int main() { - struct Foo x = {0}; - x.s1(); // expected-error {{no member named 's1' in 'struct Foo'; did you mean to use '::' instead of '.'?}} - - x.s2(); // expected-error {{no member named 's2' in 'struct Foo'; did you mean to use '::' instead of '.'?}} - return 0; -} \ No newline at end of file diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 0d94e200a00c56976f1680a66c858ba4182b8bdb..5aa3d21c4b37f2e97a3c122d7f5ce70c13db4b6e 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1597,6 +1597,10 @@ bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU)); } +bool CursorVisitor::VisitThisTypeLoc(ThisTypeLoc TL) { + return true; +} + bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { return Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)); } @@ -1809,6 +1813,7 @@ DEFAULT_TYPELOC_IMPL(FunctionProto, FunctionType) DEFAULT_TYPELOC_IMPL(FunctionNoProto, FunctionType) DEFAULT_TYPELOC_IMPL(Record, TagType) DEFAULT_TYPELOC_IMPL(Enum, TagType) +DEFAULT_TYPELOC_IMPL(Interface, TagType) DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParm, Type) DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParmPack, Type) DEFAULT_TYPELOC_IMPL(Auto, Type) @@ -6438,6 +6443,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) { case Decl::Enum: case Decl::Record: + case Decl::Interface: case Decl::CXXRecord: case Decl::ClassTemplateSpecialization: case Decl::ClassTemplatePartialSpecialization: diff --git a/clang/tools/libclang/CIndexCXX.cpp b/clang/tools/libclang/CIndexCXX.cpp index a06fe7ba4af56c224445f0af420573059bcda045..82a35159928f2774b097d0e4e6dd447888e03b6a 100644 --- a/clang/tools/libclang/CIndexCXX.cpp +++ b/clang/tools/libclang/CIndexCXX.cpp @@ -64,6 +64,7 @@ enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) { getCursorDecl(C))) { switch (PartialSpec->getTagKind()) { case TTK_Interface: + case TTK_Interface_bsc: case TTK_Struct: return CXCursor_StructDecl; case TTK_Class: return CXCursor_ClassDecl; case TTK_Union: return CXCursor_UnionDecl;