DefinitionShadower: fix crash with C++20 concepts
In principle, for a TemplateDecl, `isDefinition()` issues a recursive call passing the templated decl as a parameter. A `ConceptDecl` is derived from `TemplateDecl`, however, it should always be considered a definition. Also, update the DeclShadowing test incorporating a C++20 concept. Fixes #12779.
This commit is contained in:
parent
ad5841e05c
commit
5f576a2ba8
@ -35,7 +35,9 @@ namespace cling {
|
|||||||
&& (SM.getFileID(SM.getIncludeLoc(FID)) == SM.getMainFileID());
|
&& (SM.getFileID(SM.getIncludeLoc(FID)) == SM.getMainFileID());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Returns whether the given {Function,Tag,Var}Decl/TemplateDecl is a definition.
|
/// \brief Returns whether a declaration is a definition. A `TemplateDecl` is
|
||||||
|
/// a definition if the templated decl is itself a definition; a concept is
|
||||||
|
/// always considered a definition.
|
||||||
static bool isDefinition(const Decl *D) {
|
static bool isDefinition(const Decl *D) {
|
||||||
if (auto FD = dyn_cast<FunctionDecl>(D))
|
if (auto FD = dyn_cast<FunctionDecl>(D))
|
||||||
return FD->isThisDeclarationADefinition();
|
return FD->isThisDeclarationADefinition();
|
||||||
@ -44,7 +46,7 @@ namespace cling {
|
|||||||
if (auto VD = dyn_cast<VarDecl>(D))
|
if (auto VD = dyn_cast<VarDecl>(D))
|
||||||
return VD->isThisDeclarationADefinition();
|
return VD->isThisDeclarationADefinition();
|
||||||
if (auto TD = dyn_cast<TemplateDecl>(D))
|
if (auto TD = dyn_cast<TemplateDecl>(D))
|
||||||
return isDefinition(TD->getTemplatedDecl());
|
return isa<ConceptDecl>(TD) || isDefinition(TD->getTemplatedDecl());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,14 +6,17 @@
|
|||||||
// LICENSE.TXT for details.
|
// LICENSE.TXT for details.
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// RUN: cat %s | %cling 2>&1 | FileCheck %s
|
// RUN: cat %s | %cling 2>&1 | FileCheck --implicit-check-not error: %s
|
||||||
#include "cling/Interpreter/Interpreter.h"
|
#include "cling/Interpreter/Interpreter.h"
|
||||||
#include "cling/Utils/AST.h"
|
#include "cling/Utils/AST.h"
|
||||||
#include "clang/AST/Decl.h"
|
#include "clang/AST/Decl.h"
|
||||||
|
|
||||||
#include <type_traits>
|
#if __cplusplus > 202002L
|
||||||
|
#include <concepts>
|
||||||
|
#endif
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
unsigned _i;
|
unsigned _i;
|
||||||
struct _X {};
|
struct _X {};
|
||||||
@ -98,6 +101,18 @@ f(33)
|
|||||||
f(3.3f)
|
f(3.3f)
|
||||||
//CHECK-NEXT: (int) 21930
|
//CHECK-NEXT: (int) 21930
|
||||||
|
|
||||||
|
#if __cplusplus > 202002L
|
||||||
|
template <typename T>
|
||||||
|
concept IsIntegral = false;
|
||||||
|
|
||||||
|
// Replace concept definition; no error is expected in `constrained_fn(10)` below
|
||||||
|
template <typename T>
|
||||||
|
concept IsIntegral = std::is_integral<T>::value;
|
||||||
|
|
||||||
|
void constrained_fn(IsIntegral auto x) {}
|
||||||
|
void g() { constrained_fn(10); }
|
||||||
|
#endif
|
||||||
|
|
||||||
cling::runtime::gClingOpts->AllowRedefinition = 0;
|
cling::runtime::gClingOpts->AllowRedefinition = 0;
|
||||||
|
|
||||||
// ==== Check DeclContext
|
// ==== Check DeclContext
|
||||||
|
Loading…
Reference in New Issue
Block a user