bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID) { // OpenCL 1.1 6.8g: "The extern, static, auto and register storage-class // specifiers are not supported." // It seems sensible to prohibit private_extern too // The cl_clang_storage_class_specifiers extension enables support for // these storage-class specifiers. if (S.getLangOptions().OpenCL && !S.getOpenCLOptions().cl_clang_storage_class_specifiers) { switch (SC) { case SCS_extern: case SCS_private_extern: case SCS_auto: case SCS_register: case SCS_static: DiagID = diag::err_not_opencl_storage_class_specifier; PrevSpec = getSpecifierName(SC); return true; default: break; } } if (StorageClassSpec != SCS_unspecified) { // Maybe this is an attempt to use C++0x 'auto' outside of C++0x mode. bool isInvalid = true; if (TypeSpecType == TST_unspecified && S.getLangOptions().CPlusPlus) { if (SC == SCS_auto) return SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID); if (StorageClassSpec == SCS_auto) { isInvalid = SetTypeSpecType(TST_auto, StorageClassSpecLoc, PrevSpec, DiagID); assert(!isInvalid && "auto SCS -> TST recovery failed"); } } // Changing storage class is allowed only if the previous one // was the 'extern' that is part of a linkage specification and // the new storage class is 'typedef'. if (isInvalid && !(SCS_extern_in_linkage_spec && StorageClassSpec == SCS_extern && SC == SCS_typedef)) return BadSpecifier(SC, (SCS)StorageClassSpec, PrevSpec, DiagID); } StorageClassSpec = SC; StorageClassSpecLoc = Loc; assert((unsigned)SC == StorageClassSpec && "SCS constants overflow bitfield"); return false; }
static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() != 0) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } // Attribute can be applied only to functions or variables. if (isa<VarDecl>(D)) { D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context)); return; } FunctionDecl *FD = dyn_cast<FunctionDecl>(D); if (!FD) { // Apparently Visual C++ thinks it is okay to not emit a warning // in this case, so only emit a warning when -fms-extensions is not // specified. if (!S.getLangOptions().Microsoft) S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << 2 /*variable and function*/; return; } // Currently, the dllimport attribute is ignored for inlined functions. // Warning is emitted. if (FD->isInlineSpecified()) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; return; } // The attribute is also overridden by a subsequent declaration as dllexport. // Warning is emitted. for (AttributeList *nextAttr = Attr.getNext(); nextAttr; nextAttr = nextAttr->getNext()) { if (nextAttr->getKind() == AttributeList::AT_dllexport) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; return; } } if (D->getAttr<DLLExportAttr>()) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; return; } D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context)); }
/// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is /// valid. /// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code /// like this: /// char *bytes = reinterpret_cast\<char*\>(int_ptr); void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange, const SourceRange &DestRange) { QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType(); DestType = Self.Context.getCanonicalType(DestType); QualType SrcType = SrcExpr->getType(); if (const LValueReferenceType *DestTypeTmp = DestType->getAsLValueReferenceType()) { if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) { // Cannot cast non-lvalue to reference type. Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue) << "reinterpret_cast" << OrigDestType << SrcExpr->getSourceRange(); return; } // C++ 5.2.10p10: [...] a reference cast reinterpret_cast<T&>(x) has the // same effect as the conversion *reinterpret_cast<T*>(&x) with the // built-in & and * operators. // This code does this transformation for the checked types. DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); SrcType = Self.Context.getPointerType(SrcType); } else if (const RValueReferenceType *DestTypeTmp = DestType->getAsRValueReferenceType()) { // Both the reference conversion and the rvalue rules apply. Self.DefaultFunctionArrayConversion(SrcExpr); SrcType = SrcExpr->getType(); DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); SrcType = Self.Context.getPointerType(SrcType); } else { // C++ 5.2.10p1: [...] the lvalue-to-rvalue, array-to-pointer, and // function-to-pointer standard conversions are performed on the // expression v. Self.DefaultFunctionArrayConversion(SrcExpr); SrcType = SrcExpr->getType(); } // Canonicalize source for comparison. SrcType = Self.Context.getCanonicalType(SrcType); const MemberPointerType *DestMemPtr = DestType->getAsMemberPointerType(), *SrcMemPtr = SrcType->getAsMemberPointerType(); if (DestMemPtr && SrcMemPtr) { // C++ 5.2.10p9: An rvalue of type "pointer to member of X of type T1" // can be explicitly converted to an rvalue of type "pointer to member // of Y of type T2" if T1 and T2 are both function types or both object // types. if (DestMemPtr->getPointeeType()->isFunctionType() != SrcMemPtr->getPointeeType()->isFunctionType()) { Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic) << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; return; } // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away // constness. if (CastsAwayConstness(Self, SrcType, DestType)) { Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away) << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; return; } // A valid member pointer cast. return; } // See below for the enumeral issue. if (SrcType->isNullPtrType() && DestType->isIntegralType() && !DestType->isEnumeralType()) { // C++0x 5.2.10p4: A pointer can be explicitly converted to any integral // type large enough to hold it. A value of std::nullptr_t can be // converted to an integral type; the conversion has the same meaning // and validity as a conversion of (void*)0 to the integral type. if (Self.Context.getTypeSize(SrcType) > Self.Context.getTypeSize(DestType)) { Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_small_int) << OrigDestType << DestRange; } return; } bool destIsPtr = DestType->isPointerType(); bool srcIsPtr = SrcType->isPointerType(); if (!destIsPtr && !srcIsPtr) { // Except for std::nullptr_t->integer and lvalue->reference, which are // handled above, at least one of the two arguments must be a pointer. Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic) << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; return; } if (SrcType == DestType) { // C++ 5.2.10p2 has a note that mentions that, subject to all other // restrictions, a cast to the same type is allowed. The intent is not // entirely clear here, since all other paragraphs explicitly forbid casts // to the same type. However, the behavior of compilers is pretty consistent // on this point: allow same-type conversion if the involved types are // pointers, disallow otherwise. return; } // Note: Clang treats enumeration types as integral types. If this is ever // changed for C++, the additional check here will be redundant. if (DestType->isIntegralType() && !DestType->isEnumeralType()) { assert(srcIsPtr && "One type must be a pointer"); // C++ 5.2.10p4: A pointer can be explicitly converted to any integral // type large enough to hold it. if (Self.Context.getTypeSize(SrcType) > Self.Context.getTypeSize(DestType)) { Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_small_int) << OrigDestType << DestRange; } return; } if (SrcType->isIntegralType() || SrcType->isEnumeralType()) { assert(destIsPtr && "One type must be a pointer"); // C++ 5.2.10p5: A value of integral or enumeration type can be explicitly // converted to a pointer. return; } if (!destIsPtr || !srcIsPtr) { // With the valid non-pointer conversions out of the way, we can be even // more stringent. Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic) << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; return; } // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness. if (CastsAwayConstness(Self, SrcType, DestType)) { Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away) << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; return; } // Not casting away constness, so the only remaining check is for compatible // pointer categories. if (SrcType->isFunctionPointerType()) { if (DestType->isFunctionPointerType()) { // C++ 5.2.10p6: A pointer to a function can be explicitly converted to // a pointer to a function of a different type. return; } // C++0x 5.2.10p8: Converting a pointer to a function into a pointer to // an object type or vice versa is conditionally-supported. // Compilers support it in C++03 too, though, because it's necessary for // casting the return value of dlsym() and GetProcAddress(). // FIXME: Conditionally-supported behavior should be configurable in the // TargetInfo or similar. if (!Self.getLangOptions().CPlusPlus0x) { Self.Diag(OpRange.getBegin(), diag::ext_reinterpret_cast_fn_obj) << OpRange; } return; } if (DestType->isFunctionPointerType()) { // See above. if (!Self.getLangOptions().CPlusPlus0x) { Self.Diag(OpRange.getBegin(), diag::ext_reinterpret_cast_fn_obj) << OpRange; } return; } // C++ 5.2.10p7: A pointer to an object can be explicitly converted to // a pointer to an object of different type. // Void pointers are not specified, but supported by every compiler out there. // So we finish by allowing everything that remains - it's got to be two // object pointers. }
static unsigned long long getContextsForContextKind( enum CodeCompletionContext::Kind kind, Sema &S) { unsigned long long contexts = 0; switch (kind) { case CodeCompletionContext::CCC_OtherWithMacros: { //We can allow macros here, but we don't know what else is permissible //So we'll say the only thing permissible are macros contexts = CXCompletionContext_MacroName; break; } case CodeCompletionContext::CCC_TopLevel: case CodeCompletionContext::CCC_ObjCIvarList: case CodeCompletionContext::CCC_ClassStructUnion: case CodeCompletionContext::CCC_Type: { contexts = CXCompletionContext_AnyType | CXCompletionContext_ObjCInterface; if (S.getLangOptions().CPlusPlus) { contexts |= CXCompletionContext_EnumTag | CXCompletionContext_UnionTag | CXCompletionContext_StructTag | CXCompletionContext_ClassTag | CXCompletionContext_NestedNameSpecifier; } break; } case CodeCompletionContext::CCC_Statement: { contexts = CXCompletionContext_AnyType | CXCompletionContext_ObjCInterface | CXCompletionContext_AnyValue; if (S.getLangOptions().CPlusPlus) { contexts |= CXCompletionContext_EnumTag | CXCompletionContext_UnionTag | CXCompletionContext_StructTag | CXCompletionContext_ClassTag | CXCompletionContext_NestedNameSpecifier; } break; } case CodeCompletionContext::CCC_Expression: { contexts = CXCompletionContext_AnyValue; if (S.getLangOptions().CPlusPlus) { contexts |= CXCompletionContext_AnyType | CXCompletionContext_ObjCInterface | CXCompletionContext_EnumTag | CXCompletionContext_UnionTag | CXCompletionContext_StructTag | CXCompletionContext_ClassTag | CXCompletionContext_NestedNameSpecifier; } break; } case CodeCompletionContext::CCC_ObjCMessageReceiver: { contexts = CXCompletionContext_ObjCObjectValue | CXCompletionContext_ObjCSelectorValue | CXCompletionContext_ObjCInterface; if (S.getLangOptions().CPlusPlus) { contexts |= CXCompletionContext_CXXClassTypeValue | CXCompletionContext_AnyType | CXCompletionContext_EnumTag | CXCompletionContext_UnionTag | CXCompletionContext_StructTag | CXCompletionContext_ClassTag | CXCompletionContext_NestedNameSpecifier; } break; } case CodeCompletionContext::CCC_DotMemberAccess: { contexts = CXCompletionContext_DotMemberAccess; break; } case CodeCompletionContext::CCC_ArrowMemberAccess: { contexts = CXCompletionContext_ArrowMemberAccess; break; } case CodeCompletionContext::CCC_ObjCPropertyAccess: { contexts = CXCompletionContext_ObjCPropertyAccess; break; } case CodeCompletionContext::CCC_EnumTag: { contexts = CXCompletionContext_EnumTag | CXCompletionContext_NestedNameSpecifier; break; } case CodeCompletionContext::CCC_UnionTag: { contexts = CXCompletionContext_UnionTag | CXCompletionContext_NestedNameSpecifier; break; } case CodeCompletionContext::CCC_ClassOrStructTag: { contexts = CXCompletionContext_StructTag | CXCompletionContext_ClassTag | CXCompletionContext_NestedNameSpecifier; break; } case CodeCompletionContext::CCC_ObjCProtocolName: { contexts = CXCompletionContext_ObjCProtocol; break; } case CodeCompletionContext::CCC_Namespace: { contexts = CXCompletionContext_Namespace; break; } case CodeCompletionContext::CCC_PotentiallyQualifiedName: { contexts = CXCompletionContext_NestedNameSpecifier; break; } case CodeCompletionContext::CCC_MacroNameUse: { contexts = CXCompletionContext_MacroName; break; } case CodeCompletionContext::CCC_NaturalLanguage: { contexts = CXCompletionContext_NaturalLanguage; break; } case CodeCompletionContext::CCC_SelectorName: { contexts = CXCompletionContext_ObjCSelectorName; break; } case CodeCompletionContext::CCC_ParenthesizedExpression: { contexts = CXCompletionContext_AnyType | CXCompletionContext_ObjCInterface | CXCompletionContext_AnyValue; if (S.getLangOptions().CPlusPlus) { contexts |= CXCompletionContext_EnumTag | CXCompletionContext_UnionTag | CXCompletionContext_StructTag | CXCompletionContext_ClassTag | CXCompletionContext_NestedNameSpecifier; } break; } case CodeCompletionContext::CCC_ObjCInstanceMessage: { contexts = CXCompletionContext_ObjCInstanceMessage; break; } case CodeCompletionContext::CCC_ObjCClassMessage: { contexts = CXCompletionContext_ObjCClassMessage; break; } case CodeCompletionContext::CCC_ObjCInterfaceName: { contexts = CXCompletionContext_ObjCInterface; break; } case CodeCompletionContext::CCC_ObjCCategoryName: { contexts = CXCompletionContext_ObjCCategory; break; } case CodeCompletionContext::CCC_Other: case CodeCompletionContext::CCC_ObjCInterface: case CodeCompletionContext::CCC_ObjCImplementation: case CodeCompletionContext::CCC_Name: case CodeCompletionContext::CCC_MacroName: case CodeCompletionContext::CCC_PreprocessorExpression: case CodeCompletionContext::CCC_PreprocessorDirective: case CodeCompletionContext::CCC_TypeQualifiers: { //Only Clang results should be accepted, so we'll set all of the other //context bits to 0 (i.e. the empty set) contexts = CXCompletionContext_Unexposed; break; } case CodeCompletionContext::CCC_Recovery: { //We don't know what the current context is, so we'll return unknown //This is the equivalent of setting all of the other context bits contexts = CXCompletionContext_Unknown; break; } } return contexts; }