CustomTypeAnnotation::AnnotationReason CustomTypeAnnotation::tmplArgAnnotationReason(ArrayRef<TemplateArgument> Args) { for (const TemplateArgument &Arg : Args) { if (Arg.getKind() == TemplateArgument::Type) { QualType Type = Arg.getAsType(); if (hasEffectiveAnnotation(Type)) { AnnotationReason Reason = {Type, RK_TemplateInherited, nullptr, ""}; return Reason; } } else if (Arg.getKind() == TemplateArgument::Pack) { AnnotationReason Reason = tmplArgAnnotationReason(Arg.getPackAsArray()); if (Reason.Kind != RK_None) { return Reason; } } } AnnotationReason Reason = {QualType(), RK_None, nullptr, ""}; return Reason; }
bool CheckAllocationsInFunctionVisitor::VisitCallExpr(CallExpr* callExpr) { // Check callExpr for AllocateArray auto callee = callExpr->getDirectCallee(); if (callExpr->getNumArgs() == 3 && callee && callee->getName().equals("AllocateArray")) { VisitAllocate( [=]() { return callExpr->getArg(0); }, [=]() { return callExpr->getArg(1); }, [=]() { auto retType = callExpr->getCallReturnType(_mainVisitor->getContext()); return QualType(retType->getAs<PointerType>()->getPointeeType()); } ); } return true; }
void DynTypedNode::print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const { if (const TemplateArgument *TA = get<TemplateArgument>()) TA->print(PP, OS); else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>()) NNS->print(OS, PP); else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) NNSL->getNestedNameSpecifier()->print(OS, PP); else if (const QualType *QT = get<QualType>()) QT->print(OS, PP); else if (const TypeLoc *TL = get<TypeLoc>()) TL->getType().print(OS, PP); else if (const Decl *D = get<Decl>()) D->print(OS, PP); else if (const Stmt *S = get<Stmt>()) S->printPretty(OS, nullptr, PP); else if (const Type *T = get<Type>()) QualType(T, 0).print(OS, PP); else OS << "Unable to print values of type " << NodeKind.asStringRef() << "\n"; }
CustomTypeAnnotation::AnnotationReason CustomTypeAnnotation::directAnnotationReason(QualType T) { if (const TagDecl *D = T->getAsTagDecl()) { if (hasCustomAnnotation(D, Spelling)) { AnnotationReason Reason = {T, RK_Direct, nullptr, ""}; return Reason; } std::string ImplAnnotReason = getImplicitReason(D); if (!ImplAnnotReason.empty()) { AnnotationReason Reason = {T, RK_Implicit, nullptr, ImplAnnotReason}; return Reason; } } // Check if we have a cached answer void *Key = T.getAsOpaquePtr(); ReasonCache::iterator Cached = Cache.find(T.getAsOpaquePtr()); if (Cached != Cache.end()) { return Cached->second; } // Check if we have a type which we can recurse into if (const clang::ArrayType *Array = T->getAsArrayTypeUnsafe()) { if (hasEffectiveAnnotation(Array->getElementType())) { AnnotationReason Reason = {Array->getElementType(), RK_ArrayElement, nullptr, ""}; Cache[Key] = Reason; return Reason; } } // Recurse into Base classes if (const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl()) { if (Declaration->hasDefinition()) { Declaration = Declaration->getDefinition(); for (const CXXBaseSpecifier &Base : Declaration->bases()) { if (hasEffectiveAnnotation(Base.getType())) { AnnotationReason Reason = {Base.getType(), RK_BaseClass, nullptr, ""}; Cache[Key] = Reason; return Reason; } } // Recurse into members for (const FieldDecl *Field : Declaration->fields()) { if (hasEffectiveAnnotation(Field->getType())) { AnnotationReason Reason = {Field->getType(), RK_Field, Field, ""}; Cache[Key] = Reason; return Reason; } } // Recurse into template arguments if the annotation // MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS is present if (hasCustomAnnotation( Declaration, "moz_inherit_type_annotations_from_template_args")) { const ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Declaration); if (Spec) { const TemplateArgumentList &Args = Spec->getTemplateArgs(); AnnotationReason Reason = tmplArgAnnotationReason(Args.asArray()); if (Reason.Kind != RK_None) { Cache[Key] = Reason; return Reason; } } } } } AnnotationReason Reason = {QualType(), RK_None, nullptr, ""}; Cache[Key] = Reason; return Reason; }
int CDaoNamespace::Generate( CDaoNamespace *outer ) { header = ""; source = ""; source2 = ""; source3 = ""; onload = ""; onload2 = ""; onload3 = ""; if( unsupported ) return 0; bool isCpp = module->compiler->getPreprocessor().getLangOpts().CPlusPlus; int i, n, retcode = 0; for(i=0, n=usertypes.size(); i<n; i++) retcode |= usertypes[i]->Generate(); for(i=0, n=functions.size(); i<n; i++){ CDaoFunction *func = functions[i]; if( func->generated || func->excluded ) continue; retcode |= func->Generate(); } #if 0 map<string,int> check; for(i=0, n=usertypes.size(); i<n; i++){ CDaoUserType *ut = usertypes[i]; if( check.find( ut->qname ) != check.end() ) ut->isRedundant = true; if( ut->isRedundant || ut->IsFromRequiredModules() ) continue; check[ut->qname] = 1; } #endif header = ""; source = module->MakeSourceCodes( functions, this ); //source += module->MakeSourceCodes( usertypes, this ); //source2 = module->MakeSource2Codes( usertypes ); //source3 = module->MakeSource3Codes( usertypes ); if( nsdecl ){ string this_name = varname; string outer_name = outer ? outer->varname : "ns"; string qname = nsdecl->getQualifiedNameAsString(); string name = nsdecl->getNameAsString(); outer_name = cdao_qname_to_idname( outer_name ); if( outer == NULL || outer->nsdecl == NULL ){ header += "using namespace " + name + ";\n"; if( name == "std" ) name = "_std"; if( name == "io" ) name = "_io"; onload += "\tDaoNamespace *" + this_name + " = DaoVmSpace_GetNamespace( "; onload += "vms, \"" + name + "\" );\n"; onload2 += "\tDaoNamespace_AddConstValue( ns, \"" + name + "\", (DaoValue*) " + this_name + " );\n"; }else{ header += "using namespace " + qname + ";\n"; onload += "\tDaoNamespace *" + this_name + " = DaoNamespace_GetNamespace( "; onload += outer_name + ", \"" + name + "\" );\n"; } if( enums.size() || variables.size() || isCpp /* for constant true and false */ ){ source += module->MakeConstNumber( enums, variables, qname, isCpp ); onload2 += "\tDaoNamespace_AddConstNumbers( " + this_name; onload2 += ", dao_" + this_name + "_Nums );\n"; } onload3 += module->MakeConstStruct( variables, this_name, qname ); }else{ if( enums.size() || variables.size() ){ source += module->MakeConstNumber( enums, variables, "", isCpp ); onload2 += "\tDaoNamespace_AddConstNumbers( ns, dao__Nums );\n"; }else if( this == & module->topLevelScope && module->numericConsts.size() ){ source += module->MakeConstNumber( enums, variables, "", isCpp ); onload2 += "\tDaoNamespace_AddConstNumbers( ns, dao__Nums );\n"; } onload3 += module->MakeConstStruct( variables, "ns", "" ); } //header += module->MakeHeaderCodes( usertypes ); onload3 += module->MakeOnLoadCodes( functions, this ); //onload3 += module->MakeOnLoad2Codes( usertypes ); for(i=0, n=namespaces.size(); i<n; i++){ retcode |= namespaces[i]->Generate( this ); header += namespaces[i]->header; source += namespaces[i]->source; //source2 += namespaces[i]->source2; //source3 += namespaces[i]->source3; onload += namespaces[i]->onload; onload2 += namespaces[i]->onload2; onload3 += namespaces[i]->onload3; } //onload2 += module->MakeOnLoadCodes( this ); #if 0 string code = "\tDaoNamespace_DefineType( " + varname + ", \""; for(i=0, n=usertypes.size(); i<n; i++){ CDaoUserType *ut = usertypes[i]; if( ut->isRedundant || ut->IsFromRequiredModules() ) continue; if( dyn_cast<ClassTemplateSpecializationDecl>( ut->decl ) == NULL ) continue; QualType qtype = QualType( ut->decl->getTypeForDecl(), 0 ).getCanonicalType(); string qname = normalize_type_name( qtype.getAsString() ); string name = cdao_remove_type_scopes( qname ); string dname = cdao_make_dao_template_type_name( qname ); string dname2 = cdao_make_dao_template_type_name( ut->name2 ); if( name != ut->name2 ){ outs() << ut->qname << " " << ut->name2 << " " << name << "\n"; onload2 += code + dname + "\", \"" + dname2 + "\" );\n"; } } #endif return retcode; }
void MainVisitor::ProcessUnbarrieredFields( CXXRecordDecl* recordDecl, const PushFieldType& pushFieldType) { std::string typeName = recordDecl->getQualifiedNameAsString(); if (typeName == "Memory::WriteBarrierPtr") { return; // Skip WriteBarrierPtr itself } const auto& sourceMgr = _compilerInstance.getSourceManager(); DiagnosticsEngine& diagEngine = _context.getDiagnostics(); const unsigned diagID = diagEngine.getCustomDiagID( DiagnosticsEngine::Error, "Unbarriered field, see " "https://github.com/microsoft/ChakraCore/wiki/Software-Write-Barrier#coding-rules"); for (auto field : recordDecl->fields()) { const QualType qualType = field->getType(); string fieldTypeName = qualType.getAsString(); string fieldName = field->getNameAsString(); if (StartsWith(fieldTypeName, "WriteBarrierPtr<") || // WriteBarrierPtr fields Contains(fieldTypeName, "_no_write_barrier_policy, ")) // FieldNoBarrier { continue; // skip } // If an annotated field type is struct/class/union (RecordType), the // field type in turn should likely be annoatated. if (fieldTypeName.back() != '*' // not "... *" && ( StartsWith(fieldTypeName, "typename WriteBarrierFieldTypeTraits") || StartsWith(fieldTypeName, "WriteBarrierFieldTypeTraits") || StartsWith(fieldTypeName, "const typename WriteBarrierFieldTypeTraits") || StartsWith(fieldTypeName, "const WriteBarrierFieldTypeTraits") || fieldName.length() == 0 // anonymous union/struct )) { auto originalType = qualType->getUnqualifiedDesugaredType(); if (auto arrayType = dyn_cast<ArrayType>(originalType)) { originalType = arrayType->getElementType()->getUnqualifiedDesugaredType(); } string originalTypeName = QualType(originalType, 0).getAsString(); if (isa<RecordType>(originalType) && !StartsWith(originalTypeName, "class Memory::WriteBarrierPtr<")) { if (pushFieldType(originalType)) { Log::outs() << "Queue field type: " << originalTypeName << " (" << typeName << "::" << fieldName << ")\n"; } } } else { SourceLocation location = field->getLocStart(); if (this->_fix) { const char* begin = sourceMgr.getCharacterData(location); const char* end = begin; if (MatchType(fieldTypeName, begin, &end)) { _rewriter.ReplaceText( location, end - begin, GetFieldTypeAnnotation(qualType) + string(begin, end) + (*end == ' ' ? ")" : ") ")); _fixed = true; continue; } Log::errs() << "Fail to fix: " << fieldTypeName << " " << fieldName << "\n"; } diagEngine.Report(location, diagID); } } }
RangeExpr::RangeExpr(ExprClass Class, SourceLocation Loc, Expr *First, Expr *Second) : Expr(Class, QualType(), Loc), E1(First), E2(Second) { }
/// \brief Return the fully qualified type, including fully-qualified /// versions of any template parameters. QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx) { // In case of myType* we need to strip the pointer first, fully // qualify and attach the pointer once again. if (isa<PointerType>(QT.getTypePtr())) { // Get the qualifiers. Qualifiers Quals = QT.getQualifiers(); QT = getFullyQualifiedType(QT->getPointeeType(), Ctx); QT = Ctx.getPointerType(QT); // Add back the qualifiers. QT = Ctx.getQualifiedType(QT, Quals); return QT; } // In case of myType& we need to strip the reference first, fully // qualify and attach the reference once again. if (isa<ReferenceType>(QT.getTypePtr())) { // Get the qualifiers. bool IsLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr()); Qualifiers Quals = QT.getQualifiers(); QT = getFullyQualifiedType(QT->getPointeeType(), Ctx); // Add the r- or l-value reference type back to the fully // qualified one. if (IsLValueRefTy) QT = Ctx.getLValueReferenceType(QT); else QT = Ctx.getRValueReferenceType(QT); // Add back the qualifiers. QT = Ctx.getQualifiedType(QT, Quals); return QT; } // Remove the part of the type related to the type being a template // parameter (we won't report it as part of the 'type name' and it // is actually make the code below to be more complex (to handle // those) while (isa<SubstTemplateTypeParmType>(QT.getTypePtr())) { // Get the qualifiers. Qualifiers Quals = QT.getQualifiers(); QT = dyn_cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar(); // Add back the qualifiers. QT = Ctx.getQualifiedType(QT, Quals); } NestedNameSpecifier *Prefix = nullptr; Qualifiers PrefixQualifiers; ElaboratedTypeKeyword Keyword = ETK_None; if (const auto *ETypeInput = dyn_cast<ElaboratedType>(QT.getTypePtr())) { QT = ETypeInput->getNamedType(); Keyword = ETypeInput->getKeyword(); } // Create a nested name specifier if needed (i.e. if the decl context // is not the global scope. Prefix = createNestedNameSpecifierForScopeOf(Ctx, QT.getTypePtr(), true /*FullyQualified*/); // move the qualifiers on the outer type (avoid 'std::const string'!) if (Prefix) { PrefixQualifiers = QT.getLocalQualifiers(); QT = QualType(QT.getTypePtr(), 0); } // In case of template specializations iterate over the arguments and // fully qualify them as well. if (isa<const TemplateSpecializationType>(QT.getTypePtr()) || isa<const RecordType>(QT.getTypePtr())) { // We are asked to fully qualify and we have a Record Type (which // may pont to a template specialization) or Template // Specialization Type. We need to fully qualify their arguments. Qualifiers Quals = QT.getLocalQualifiers(); const Type *TypePtr = getFullyQualifiedTemplateType(Ctx, QT.getTypePtr()); QT = Ctx.getQualifiedType(TypePtr, Quals); } if (Prefix || Keyword != ETK_None) { QT = Ctx.getElaboratedType(Keyword, Prefix, QT); QT = Ctx.getQualifiedType(QT, PrefixQualifiers); } return QT; }
/// \brief Convert the specified DeclSpec to the appropriate type object. QualType Sema::ActOnTypeName(ASTContext &C, DeclSpec &DS) { QualType Result; switch (DS.getTypeSpecType()) { case DeclSpec::TST_integer: Result = C.IntegerTy; break; case DeclSpec::TST_unspecified: // FIXME: Correct? case DeclSpec::TST_real: Result = C.RealTy; break; case DeclSpec::TST_character: if(DS.isStarLengthSelector()) Result = C.NoLengthCharacterTy; else if(DS.hasLengthSelector()) Result = QualType(C.getCharacterType( EvalAndCheckCharacterLength(DS.getLengthSelector())), 0); else Result = C.CharacterTy; break; case DeclSpec::TST_logical: Result = C.LogicalTy; break; case DeclSpec::TST_complex: Result = C.ComplexTy; break; case DeclSpec::TST_struct: if(!DS.getRecord()) Result = C.RealTy; else Result = C.getRecordType(DS.getRecord()); break; } Type::TypeKind Kind = Type::NoKind; if(DS.hasKindSelector()) Kind = EvalAndCheckTypeKind(Result, DS.getKindSelector()); if(Kind != Type::NoKind || DS.isDoublePrecision() || DS.isByte()) { switch (DS.getTypeSpecType()) { case DeclSpec::TST_integer: Result = Kind == Type::NoKind? C.IntegerTy : QualType(C.getBuiltinType(BuiltinType::Integer, Kind, true), 0); break; case DeclSpec::TST_real: Result = Kind == Type::NoKind? (DS.isDoublePrecision()? C.DoublePrecisionTy : C.RealTy) : QualType(C.getBuiltinType(BuiltinType::Real, Kind, true), 0); break; case DeclSpec::TST_logical: Result = Kind == Type::NoKind? (DS.isByte()? C.ByteTy : C.LogicalTy) : QualType(C.getBuiltinType(BuiltinType::Logical, Kind, true), 0); break; case DeclSpec::TST_complex: Result = Kind == Type::NoKind? (DS.isDoublePrecision()? C.DoubleComplexTy : C.ComplexTy) : QualType(C.getBuiltinType(BuiltinType::Complex, Kind, true), 0); break; default: break; } } if (!DS.hasAttributes()) return Result; const Type *TypeNode = Result.getTypePtr(); Qualifiers Quals = Qualifiers::fromOpaqueValue(DS.getAttributeSpecs()); Quals.setIntentAttr(DS.getIntentSpec()); Quals.setAccessAttr(DS.getAccessSpec()); Result = C.getExtQualType(TypeNode, Quals); if (!Quals.hasAttributeSpec(Qualifiers::AS_dimension)) return Result; return ActOnArraySpec(C, Result, DS.getDimensions()); }