From 57e708338b585db3186e493e100ea32324ad900a Mon Sep 17 00:00:00 2001 From: malte_langkabel Date: Mon, 21 Nov 2016 16:31:35 +0100 Subject: [PATCH] logic: fixed potential crash when solving decls in lambda captures * fixed potential crash when solving decls in lambda captures * fixed solving type of anonymous structs/classes in c code * added null checks in name resolvers --- src/lib_cxx/data/parser/cxx/CxxAstVisitor.cpp | 6 +- .../cxx/name_resolver/CxxDeclNameResolver.cpp | 129 ++++++++++-------- .../CxxTemplateArgumentNameResolver.cpp | 11 +- .../cxx/name_resolver/CxxTypeNameResolver.cpp | 62 +++++---- 4 files changed, 122 insertions(+), 86 deletions(-) diff --git a/src/lib_cxx/data/parser/cxx/CxxAstVisitor.cpp b/src/lib_cxx/data/parser/cxx/CxxAstVisitor.cpp index 4ae37f1d..0e3012f0 100644 --- a/src/lib_cxx/data/parser/cxx/CxxAstVisitor.cpp +++ b/src/lib_cxx/data/parser/cxx/CxxAstVisitor.cpp @@ -312,13 +312,13 @@ bool CxxAstVisitor::TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc bool CxxAstVisitor::TraverseLambdaCapture(clang::LambdaExpr *lambdaExpr, const clang::LambdaCapture *capture) { - clang::VarDecl* d = capture->getCapturedVar(); if (lambdaExpr->isInitCapture(capture)) { - TraverseDecl(d); + TraverseDecl(capture->getCapturedVar()); } - else + else if (capture->capturesVariable()) { + clang::VarDecl* d = capture->getCapturedVar(); SymbolKind symbolKind = getSymbolKind(d); if (symbolKind == SYMBOL_LOCAL_VARIABLE || symbolKind == SYMBOL_PARAMETER) { diff --git a/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp b/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp index 93ac8c61..fd3e91f6 100644 --- a/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp +++ b/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp @@ -38,6 +38,12 @@ std::shared_ptr CxxDeclNameResolver::getName(const clang::NamedDecl } } + if ((clang::isa(declaration)) && + (clang::dyn_cast(declaration)->isLambda())) + { + declaration = clang::dyn_cast(declaration)->getLambdaCallOperator(); + } + std::shared_ptr declName; if (declaration) { @@ -94,60 +100,9 @@ std::shared_ptr CxxDeclNameResolver::getDeclName(const clang::Named return getDeclName(templatedDeclaration); } } - if (const clang::CXXRecordDecl* recordDecl = clang::dyn_cast_or_null(declaration)) + if (const clang::RecordDecl* recordDecl = clang::dyn_cast_or_null(declaration)) { - clang::ClassTemplateDecl* templateClassDeclaration = recordDecl->getDescribedClassTemplate(); - if (templateClassDeclaration) - { - return getDeclName(templateClassDeclaration); - } - else if (clang::isa(declaration)) - { - const clang::ClassTemplatePartialSpecializationDecl* partialSpecializationDecl = - clang::dyn_cast(declaration); - - clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters(); - unsigned int currentParameterIndex = 0; - - std::vector templateParameters; - const clang::TemplateArgumentList& templateArgumentList = partialSpecializationDecl->getTemplateArgs(); - const int templateArgumentCount = templateArgumentList.size(); - for (int i = 0; i < templateArgumentCount; i++) - { - const clang::TemplateArgument& templateArgument = templateArgumentList.get(i); - if (templateArgument.isDependent()) // IMPORTANT_TODO: fix case when arg depends on template parameter of outer template class, or depends on first template parameter. - { - if(currentParameterIndex < parameterList->size()) - { - templateParameters.push_back(getTemplateParameterString(parameterList->getParam(currentParameterIndex))); - } - else - { - //this if fixes the crash, but not the problem TODO - // const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager(); - // LOG_ERROR("Template getParam out of Range " + declaration->getLocation().printToString(sourceManager)); - } - currentParameterIndex++; - } - else - { - templateParameters.push_back(getTemplateArgumentName(templateArgument)); - } - } - - return std::make_shared(declNameString, templateParameters); - } - else if (clang::isa(declaration)) - { - std::vector templateArguments; - const clang::TemplateArgumentList& templateArgumentList = clang::dyn_cast(declaration)->getTemplateArgs(); - for (size_t i = 0; i < templateArgumentList.size(); i++) - { - templateArguments.push_back(getTemplateArgumentName(templateArgumentList.get(i))); - } - return std::make_shared(declNameString, templateArguments); - } - else if (recordDecl->isLambda()) + if (recordDecl->isLambda()) { // we skip this node because its child (the lambda call operator) has already been recorded. return std::shared_ptr(); @@ -159,6 +114,60 @@ std::shared_ptr CxxDeclNameResolver::getDeclName(const clang::Named const std::string symbolKindName = (recordDecl->isStruct() ? "struct" : "class"); return std::make_shared(getNameForAnonymousSymbol(symbolKindName, presumedBegin), std::vector()); } + else if (const clang::CXXRecordDecl* cxxRecordDecl = clang::dyn_cast_or_null(declaration)) + { + clang::ClassTemplateDecl* templateClassDeclaration = cxxRecordDecl->getDescribedClassTemplate(); + if (templateClassDeclaration) + { + return getDeclName(templateClassDeclaration); + } + else if (clang::isa(declaration)) + { + const clang::ClassTemplatePartialSpecializationDecl* partialSpecializationDecl = + clang::dyn_cast(declaration); + + clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters(); + unsigned int currentParameterIndex = 0; + + std::vector templateParameters; + const clang::TemplateArgumentList& templateArgumentList = partialSpecializationDecl->getTemplateArgs(); + const int templateArgumentCount = templateArgumentList.size(); + for (int i = 0; i < templateArgumentCount; i++) + { + const clang::TemplateArgument& templateArgument = templateArgumentList.get(i); + if (templateArgument.isDependent()) // IMPORTANT_TODO: fix case when arg depends on template parameter of outer template class, or depends on first template parameter. + { + if(currentParameterIndex < parameterList->size()) + { + templateParameters.push_back(getTemplateParameterString(parameterList->getParam(currentParameterIndex))); + } + else + { + //this if fixes the crash, but not the problem TODO + // const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager(); + // LOG_ERROR("Template getParam out of Range " + declaration->getLocation().printToString(sourceManager)); + } + currentParameterIndex++; + } + else + { + templateParameters.push_back(getTemplateArgumentName(templateArgument)); + } + } + + return std::make_shared(declNameString, templateParameters); + } + else if (clang::isa(declaration)) + { + std::vector templateArguments; + const clang::TemplateArgumentList& templateArgumentList = clang::dyn_cast(declaration)->getTemplateArgs(); + for (size_t i = 0; i < templateArgumentList.size(); i++) + { + templateArguments.push_back(getTemplateArgumentName(templateArgumentList.get(i))); + } + return std::make_shared(declNameString, templateArguments); + } + } } else if (clang::isa(declaration)) { @@ -167,7 +176,6 @@ std::shared_ptr CxxDeclNameResolver::getDeclName(const clang::Named std::string functionName = declNameString; std::vector templateArguments; - if ((clang::dyn_cast_or_null(functionDecl)) && (clang::dyn_cast_or_null(functionDecl)->getParent()->isLambda())) { @@ -325,14 +333,23 @@ std::string CxxDeclNameResolver::getTemplateParameterTypeString(const clang::Non { typeNameResolver.ignoreContextDecl(m_currentDecl); } + + std::string typeString = ""; - std::string typeString = typeNameResolver.getName(parameter->getType())->toString(); + std::shared_ptr typeName = typeNameResolver.getName(parameter->getType()); + if (typeName) + { + typeString = typeName->toString(); + } + else + { + LOG_WARNING("unable to solve type of non-type template parameter declaration"); + } if (parameter->isTemplateParameterPack()) { typeString += "..."; } - return typeString; } diff --git a/src/lib_cxx/data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp b/src/lib_cxx/data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp index 0865eb08..f43c8b7a 100644 --- a/src/lib_cxx/data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp +++ b/src/lib_cxx/data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp @@ -30,7 +30,16 @@ std::string CxxTemplateArgumentNameResolver::getTemplateArgumentName(const clang case clang::TemplateArgument::Type: { CxxTypeNameResolver typeNameResolver(getIgnoredContextDecls()); - return typeNameResolver.getName(argument.getAsType())->toString(); + std::shared_ptr typeName = typeNameResolver.getName(argument.getAsType()); + if (typeName) + { + return typeName->toString(); + } + else + { + LOG_WARNING("Unable to solve name for template type argument"); + } + break; } case clang::TemplateArgument::Integral: case clang::TemplateArgument::Null: diff --git a/src/lib_cxx/data/parser/cxx/name_resolver/CxxTypeNameResolver.cpp b/src/lib_cxx/data/parser/cxx/name_resolver/CxxTypeNameResolver.cpp index 58f45a66..9b27adbe 100644 --- a/src/lib_cxx/data/parser/cxx/name_resolver/CxxTypeNameResolver.cpp +++ b/src/lib_cxx/data/parser/cxx/name_resolver/CxxTypeNameResolver.cpp @@ -26,7 +26,7 @@ CxxTypeNameResolver::~CxxTypeNameResolver() std::shared_ptr CxxTypeNameResolver::getName(const clang::QualType& qualType) { std::shared_ptr typeName = getName(qualType.getTypePtr()); - if (qualType.isConstQualified()) + if (typeName && qualType.isConstQualified()) { typeName->addQualifier(CxxQualifierFlags::QUALIFIER_CONST); } @@ -48,12 +48,14 @@ std::shared_ptr CxxTypeNameResolver::getName(const clang::Type* typ { CxxDeclNameResolver declNameResolver(getIgnoredContextDecls()); std::shared_ptr declName = declNameResolver.getName(type->getAs()->getDecl()); - - typeName = std::make_shared( - declName->getName(), - std::vector(), - declName->getParent() - ); + if (declName) + { + typeName = std::make_shared( + declName->getName(), + std::vector(), + declName->getParent() + ); + } break; } case clang::Type::MemberPointer: @@ -92,12 +94,14 @@ std::shared_ptr CxxTypeNameResolver::getName(const clang::Type* typ { CxxDeclNameResolver declNameResolver(getIgnoredContextDecls()); std::shared_ptr declName = declNameResolver.getName(type->getAs()->getDecl()); - - typeName = std::make_shared( - declName->getName(), - std::vector(), - declName->getParent() - ); + if (declName) + { + typeName = std::make_shared( + declName->getName(), + std::vector(), + declName->getParent() + ); + } break; } case clang::Type::Builtin: @@ -118,12 +122,14 @@ std::shared_ptr CxxTypeNameResolver::getName(const clang::Type* typ { CxxDeclNameResolver declNameResolver(getIgnoredContextDecls()); std::shared_ptr declName = declNameResolver.getName(tagType->getDecl()); - - typeName = std::make_shared( - declName->getName(), - declName->getTemplateParameterNames(), - declName->getParent() - ); + if (declName) + { + typeName = std::make_shared( + declName->getName(), + declName->getTemplateParameterNames(), + declName->getParent() + ); + } } else // specialization of a template template parameter (no concrete class) important, may help: has no underlying decl! { @@ -141,7 +147,9 @@ std::shared_ptr CxxTypeNameResolver::getName(const clang::Type* typ } typeName = std::make_shared( - declName->getName(), templateArguments, declName->getParent() + declName->getName(), + templateArguments, + declName->getParent() ); } else @@ -155,12 +163,14 @@ std::shared_ptr CxxTypeNameResolver::getName(const clang::Type* typ { CxxDeclNameResolver declNameResolver(getIgnoredContextDecls()); std::shared_ptr declName = declNameResolver.getName(clang::dyn_cast(type)->getDecl()); - - typeName = std::make_shared( - declName->getName(), - declName->getTemplateParameterNames(), - declName->getParent() - ); + if (declName) + { + typeName = std::make_shared( + declName->getName(), + declName->getTemplateParameterNames(), + declName->getParent() + ); + } break; } case clang::Type::SubstTemplateTypeParm: